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!
Execute the complete statement and return the correct result
problem analysis
1、EXPLAIN EXTENDED
EXPLAIN EXTENDED
SELECT * FROM USER WHERE NAME IN (
SELECT NAME FROM blacklist WHERE TYPE=1 AND age>10
);
2. SHOW WARNINGS;
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
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
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
);
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."