SQL 相关子查询的执行顺序
SQL order of execution for correlated subquery
我有以下人员table:
+---------+----------+-------------+
| name | dept_nbr | job_title |
+---------+----------+-------------+
| Michael | 14 | Programmer |
| Kumar | 14 | Programmer |
| Dave | 14 | Programmer |
| Jane | 14 | Manager |
| Carol | 37 | Programmer |
| Joe | 37 | Programmer |
| John | 59 | CEO |
+---------+----------+-------------+
问题:查找所有 dept_nbr 的(部门)少于 3 个程序员。
工作查询:
SELECT DISTINCT dept_nbr
FROM Personnel AS P1
WHERE (SELECT COUNT(P2.dept_nbr)
FROM Personnel AS P2
WHERE P1.dept_nbr = P2.dept_nbr AND P2.job_title = 'Programmer') < 3;
结果:
37
59
备注:
部门 14 正确地不包括在内,因为它有 3 个程序员(3 等于但不少于 3)。 59部门的程序员为零,也正确地包含在结果中。
我的问题:
当上述查询执行时,通用 SQL 引擎如何进行?根据我的阅读,SQL 执行顺序(大致)是:From、Where、Group By、Having 和 Select。那么,下面的说法正确吗?
1 - 外部查询将人员 table 的每一行作为 P1 传递给内部查询。
2.a - Inner Query扫描整个Personneltable为P2,逐行查找满足条件[=68的行=].
2.b – 内部查询完成整个 table 后,它计算匹配的 dept_nbr 值和 returns 它到外部查询。
3 –在Outer Query中,如果Inner Query返回的count满足条件"WHERE (Inner Query Count Result) < 3",则P1行对应的dept_nbr已选择。
4 – 在外部查询处理的所有行之后,外部查询对结果执行 DISTINCT 并显示唯一的 dept_nbr 值。
我上面的理解对吗?具体来说,外部查询是否在最后(第 4 步)执行 DISTINCT?看起来这样,内部查询做了冗余扫描(比如它处理了四次dept_nbr = 14,当它在第一遍真正有答案时)。
我在 sqlfiddle.com w/ MySQL 5.6.
上测试了上述查询
在您的查询之前添加 EXPLAIN
(或 EXPLAIN EXTENDED
),它应该会为您提供解释计划,其中将按照您的查询顺序准确详细说明步骤。在尝试优化查询时,这是一个非常有用的工具。
When the above query executes, how does a generic SQL engine proceed?
From what I have read, SQL execution order is (roughly): From, Where,
Group By, Having, and Select.
这种说法通常是不正确的。 SQL 按照您描述的顺序 解析 。但是,execution 是由优化器决定的,可能与原始查询关系不大。请记住:SQL 是一种描述性语言,而不是过程性语言。它描述的是结果集,而不是计算它的具体步骤。
也就是说,MySQL 的执行计划比大多数其他数据库(特别是具有更好优化器的更高级数据库)更接近查询。而且,几乎所有数据库都将按照您为该查询描述的步骤进行。子查询中的聚合限制了优化的选择。
如果要消除冗余,则在过滤之前select distinct
:
SELECT dept_nbr
FROM (SELECT DISTINCT dept_nbr FROM Personnel P1) P1
WHERE (SELECT COUNT(P2.dept_nbr)
FROM Personnel AS P2
WHERE P1.dept_nbr = P2.dept_nbr AND P2.job_title = 'Programmer'
) < 3;
您还可以通过聚合更简单地完成此操作:
select dept_nbr
from personnel
group by dept_nbr
having sum(job_title = 'Programmer') < 3;
我有以下人员table:
+---------+----------+-------------+
| name | dept_nbr | job_title |
+---------+----------+-------------+
| Michael | 14 | Programmer |
| Kumar | 14 | Programmer |
| Dave | 14 | Programmer |
| Jane | 14 | Manager |
| Carol | 37 | Programmer |
| Joe | 37 | Programmer |
| John | 59 | CEO |
+---------+----------+-------------+
问题:查找所有 dept_nbr 的(部门)少于 3 个程序员。
工作查询:
SELECT DISTINCT dept_nbr
FROM Personnel AS P1
WHERE (SELECT COUNT(P2.dept_nbr)
FROM Personnel AS P2
WHERE P1.dept_nbr = P2.dept_nbr AND P2.job_title = 'Programmer') < 3;
结果:
37
59
备注:
部门 14 正确地不包括在内,因为它有 3 个程序员(3 等于但不少于 3)。 59部门的程序员为零,也正确地包含在结果中。
我的问题:
当上述查询执行时,通用 SQL 引擎如何进行?根据我的阅读,SQL 执行顺序(大致)是:From、Where、Group By、Having 和 Select。那么,下面的说法正确吗?
1 - 外部查询将人员 table 的每一行作为 P1 传递给内部查询。
2.a - Inner Query扫描整个Personneltable为P2,逐行查找满足条件[=68的行=].
2.b – 内部查询完成整个 table 后,它计算匹配的 dept_nbr 值和 returns 它到外部查询。
3 –在Outer Query中,如果Inner Query返回的count满足条件"WHERE (Inner Query Count Result) < 3",则P1行对应的dept_nbr已选择。
4 – 在外部查询处理的所有行之后,外部查询对结果执行 DISTINCT 并显示唯一的 dept_nbr 值。
我上面的理解对吗?具体来说,外部查询是否在最后(第 4 步)执行 DISTINCT?看起来这样,内部查询做了冗余扫描(比如它处理了四次dept_nbr = 14,当它在第一遍真正有答案时)。
我在 sqlfiddle.com w/ MySQL 5.6.
上测试了上述查询在您的查询之前添加 EXPLAIN
(或 EXPLAIN EXTENDED
),它应该会为您提供解释计划,其中将按照您的查询顺序准确详细说明步骤。在尝试优化查询时,这是一个非常有用的工具。
When the above query executes, how does a generic SQL engine proceed? From what I have read, SQL execution order is (roughly): From, Where, Group By, Having, and Select.
这种说法通常是不正确的。 SQL 按照您描述的顺序 解析 。但是,execution 是由优化器决定的,可能与原始查询关系不大。请记住:SQL 是一种描述性语言,而不是过程性语言。它描述的是结果集,而不是计算它的具体步骤。
也就是说,MySQL 的执行计划比大多数其他数据库(特别是具有更好优化器的更高级数据库)更接近查询。而且,几乎所有数据库都将按照您为该查询描述的步骤进行。子查询中的聚合限制了优化的选择。
如果要消除冗余,则在过滤之前select distinct
:
SELECT dept_nbr
FROM (SELECT DISTINCT dept_nbr FROM Personnel P1) P1
WHERE (SELECT COUNT(P2.dept_nbr)
FROM Personnel AS P2
WHERE P1.dept_nbr = P2.dept_nbr AND P2.job_title = 'Programmer'
) < 3;
您还可以通过聚合更简单地完成此操作:
select dept_nbr
from personnel
group by dept_nbr
having sum(job_title = 'Programmer') < 3;