[英]SQL order of execution for 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 -外部查詢將Personnel表的每一行作為P1傳遞到Inner查詢中。
2.a -內部查詢將整個Personnel表掃描為P2,逐行查找滿足條件“P1.dept_nbr = P2.dept_nbr AND P2.job_title ='Programmer'”的行。
2.b -一旦內部查詢完成整個表,它就會對匹配的dept_nbr值進行COUNT並將其返回給外部查詢。
3 -在外部查詢中,如果從內部查詢返回的計數滿足條件“WHERE(內部查詢計數結果)<3”,則P1行的對應dept_nbr被選中。
4 -在外部查詢處理的所有行之后,外部查詢對結果執行DISTINCT並顯示唯一的dept_nbr值。
我的理解是否正確? 具體來說,外部查詢是否在最后執行DISTINCT(步驟#4)? 看來,通過這種方式,內部查詢會執行冗余掃描(例如,它會在第一次傳遞中確實得到答案時四次處理dept_nbr = 14)。
我在sqlfiddle.com上用MySQL 5.6測試了上面的查詢。
執行上述查詢時,通用SQL引擎如何繼續? 根據我的閱讀,SQL執行順序是(粗略地):From,Where,Group By,Having和Select。
這句話 - 通常 - 不正確。 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;
在查詢之前添加EXPLAIN
(或EXPLAIN EXTENDED
),它應該為您提供解釋計划,該計划將詳細說明查詢順序的步驟。 在嘗試優化查詢時,這是一個非常有用的工具。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.