相关子查询

时间:2017-08-09 21:43:39

标签: mysql sql subquery correlated-subquery

我有以下人员表

+---------+----------+-------------+
| 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         |
+---------+----------+-------------+

问题:找到所有程序员少于3人的dept_nbr(部门)。

工作查询

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 - 外部查询将人员表的每一行作为P1传递给内部查询。

2.a - 内部查询将整个人员表扫描为P2,逐行,查找满足条件的行&#34; P1.dept_nbr = P2.dept_nbr AND P2。 job_title =&#39;程序员&#39;&#34;。

2.b - 内部查询完成整个表后,它会对匹配的dept_nbr值进行计数并将其返回给外部查询。

3 - 在外部查询中,如果从内部查询返回的计数满足条件&#34; WHERE(内部查询计数结果)&lt; 3&#34;,P1行的相应dept_nbr是SELECTed。

4 - 在外部查询处理的所有行之后,外部查询对结果执行DISTINCT并显示唯一的dept_nbr值。

我的理解是否正确?具体来说,外部查询是否在最后执行DISTINCT(步骤#4)?看来,通过这种方式,内部查询会执行冗余扫描(例如,它会在第一次传递中确实有答案的情况下处理dept_nbr = 14四次。)

我在sqlfiddle.com上使用MySQL 5.6测试了上述查询。

2 个答案:

答案 0 :(得分:2)

  

执行上述查询时,通用SQL引擎如何进行?   根据我的阅读,SQL执行顺序是(粗略地):From,Where,   分组依据,拥有和选择。

这句话 - 通常 - 不正确。 SQL按您描述的顺序解析。但是,执行由优化程序确定,可能与原始查询几乎没有关系。请记住: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;

答案 1 :(得分:1)

在查询之前添加EXPLAIN(或EXPLAIN EXTENDED),它应该为您提供解释计划,该计划将详细说明查询顺序的步骤。在尝试优化查询时,这是一个非常有用的工具。