SQL相关子查询是什么?和嵌套子查询有什么区别?
两者的各种叫法
- 相关子查询叫做:
Correlated Subqueries
- 非相关子查询也叫普通子查询或嵌套子查询:
Nested SubQueries
相关子查询MySQL解释
相关子查询是一个子查询中引用了某张表且这张表也在子查询外部被使用到。比如:
SELECT * FROM t1
WHERE column1 IN (
SELECT column1 FROM t2
WHERE t2.column2 = t1.column2);
请注意子查询有一个t1表column2的引用,尽管子查询的from语句中没有涉及t1表,这时mysql执行子查询却发现t1表在外部查询中。
假设表t1有一行数据(column1=5,column2=6),与此同时表t2有一行数据(column1=5,column2=7)。
如果是简单的子查询:
... WHERE column1 = ANY (SELECT column1 FROM t2)
结果将会是true,有数据返回。但是在这个例子中,where子句中的子查询会返回false,查不到任何数据,因为两张表的column2不匹配。
相关子查询
和普通子查询
(也叫非相关子查询
)的差别就在于这子查询中是否有对外部查询中涉及到的表的引用。
规则范围: MySQL从内到外执行执行。比如:
SELECT column1 FROM t1 AS x
WHERE x.column1 = (SELECT column1 FROM t2 AS x
WHERE x.column1 = (SELECT column1 FROM t3
WHERE x.column2 = t3.column1));
在这条语句中,x.column2
一定是表t2的列,因为查询SELECT column1 FROM t2 AS x ...
别名是x,它不是表t1的列是因为SELECT column1 FROM t1 ...
是一个外部查询。它俩中间还隔着一对圆括号。
相关子查询Wikipedia解释
相关子查询是使用外部查询中的值的子查询(嵌套在另一个查询中的查询)。因为子查询需为外部查询返回的每一行执行一次,所以它可能会很慢。
SELECT employee_number, name
FROM employees emp
WHERE salary > (
SELECT AVG(salary)
FROM employees
WHERE department = emp.department);
在上面的查询中,外部查询为:
SELECT employee_number, name
FROM employees emp
WHERE salary > ...
内部查询(相关子查询)为:
SELECT AVG(salary)
FROM employees
WHERE department = emp.department
在上面的嵌套查询中,须为每个员工重新执行内部查询。
相关子查询执行步骤拆解
看完官方和Wiki的解释,对相关子查询的描述基本一样,用自己的话说就是:
相关子查询被用来做逐行的处理,子查询会为外部查询出来的每一行执行内部SQL。(外部语句也可为update或delete语句)
可拆分成下面三个步骤:
- 外部查询拿到所有行
- 内部查询使用外部查询出来的每一行来执行自己逻辑
- 内部查询有结果返回则当前外部行被保留最终返回否则继续执行下一行
相关子查询和嵌套查询的区别
- 执行顺序:相关子查询是由外部查询驱动内部查询。 而正常的嵌套查询中,内部查询首先被立即执行,返回的值被外部查询使用并执行外部查询。
- 依赖性:相关子查询内部查询依赖于外部查询进行处理,而在嵌套查询中外部查询依赖于内部查询。
- 性能:使用相关子查询会使性能降低,因为它执行的次数远远大于嵌套查询的次数