in subquery related

Link to the original text (this article is not part of the original text): https://blog.csdn.net/weixin_33331978/article/details/113123563

In subquery syntax error, but does not affect the correctness of the entire query

user table

id name age
1 A 9
2 B 11
3 C 15
4 D 13

blacklist table

id name type
1 B 1
2 C 0
3 D 1

Error process

Purpose: Check all information of male users who are older than 10 in the blacklist.
Correct sentence

select * from user where name in (
	select name from blacklist where type = 1
) and age > 10;

Error statement

SELECT * FROM usr WHERE NAME IN (
	SELECT NAME FROM blacklist WHERE TYPE=1 AND age>10
);

The age condition is added to the in query, but the blacklist has no age field.

Execute the subquery alone and report an error!
Insert picture description here
Execute the complete statement and return the correct result
Insert picture description here

problem analysis

1、EXPLAIN EXTENDED

EXPLAIN EXTENDED 
SELECT * FROM USER WHERE NAME IN (
	SELECT NAME FROM blacklist WHERE TYPE=1 AND age>10
);

Insert picture description here
2. SHOW WARNINGS;
Insert picture description here
3. Analyze the sentence

Field or reference 'test.USER.age' of SELECT #2 was resolved in SELECT #1
select `test`.`user`.`id` AS `id`,`test`.`user`.`name` AS `name`,`test`.`user`.`age` AS `age` 
from `test`.`user` where <in_optimizer>(`test`.`user`.`name`,<exists>(
		select 1 from `test`.`blacklist` where(
		(`test`.`blacklist`.`type` = 1) and (`test`.`user`.`age` > 10) and (<cache>(`test`.`user`.`name`) = `test`.`blacklist`.`name`)
		)
	)
)

Simply put, after database optimization, each field points to the correct table.

Interview answer : Generally speaking, I will try it first, explain or explain extended, and then show warnings


Compared with the article , after I explained, show warnings; nothing happens.
So I used explain extended, but the result of my show warnings is not the same as his. The result is join, but mine is not.

It can be seen that the database changed the original query to a join query, and each field points to the correct table.

The specific problem needs to be confirmed. It is estimated that it is a version problem?

in is replaced by exists

If there are grammatical errors in in that are not exposed, change in to exists and try:

SELECT * FROM USER WHERE EXISTS (
	SELECT NAME FROM blacklist WHERE TYPE = 1 AND age > 10
);

Result: The
Insert picture description here
result is incorrect, and EXISTS returns a boolean value. As long as the subquery returns the number of rows, the where condition is true. Therefore, the change of select name to select 1 is also true, that is, the result is the same as before.

 select * from user where EXISTS (
	 select 1 from blacklist where type = 1 and age > 10
 );

The result is the same as before
Insert picture description here

analysis

EXPLAIN EXTENDED SELECT * FROM USER WHERE EXISTS (SELECT NAME FROM blacklist WHERE TYPE = 1 AND age > 10);
SHOW WARNINGS; 

result:

Field or reference 'test.user.age' of SELECT #2 was resolved in SELECT #1
select `test`.`user`.`id` AS `id`,`test`.`user`.`name` AS `name`,`test`.`user`.`age` AS `age` 
	from `test`.`user` where exists(
		select `test`.`blacklist`.`name` from `test`.`blacklist` where (
			(`test`.`blacklist`.`type` = 1) and (`test`.`user`.`age` > 10)
	)
)

Using exists, low-level errors are also optimized. If you want to get the data we expect, you need to add a condition in the exists subquery

select * from user a where EXISTS (
	select 1 from blacklist where type = 1 and name = a.name and age > 10
);

Insert picture description here

exists can be seen as a loop

List result = new ArrayList<>();

List user = new ArrayList<>();
for (int i = 0; i < user.size(); i++){
    
    
	if (exists(black.type == 1 && black.name.equals(user.get(i).name)) && user.get(i).age > 10){
    
    
		result.add(user.get(i));
	}
}

The difference between N and Exists

Exists: First execute the external query statement, and then execute the subquery. In the subquery, it will execute the query of the database every time, and the number of executions is equal to the number of data of the external query.

In: first query the data of the in() subquery (1 time), and put the data in the memory (no need to query multiple times), and then query and filter the external query table according to the query results, and finally return the results.

In is a hash connection between the outer table and the inner table, while exists is a loop loop of the outer table, and each time the loop loops, the inner table is queried.


to sum up

The syntax error in the in clause may not affect the execution of the entire statement.

other

There is an explain command in the MySQL database. Its main function is to analyze the operation effect of the select statement. For example, explain can obtain the index and sorting conditions used by the select statement.

The extended extension of explain can provide additional query optimization information on the basis of the original explain, which can be obtained through the MySQL show warnings command.

"From the output of MySQL explain extend, we can see how SQL is executed, which is very helpful for analyzing SQL."

Guess you like

Origin blog.csdn.net/root_zhb/article/details/115028656