如何正確理解SQL關聯子查詢


一、基本邏輯

對於外部查詢返回的每一行數據,內部查詢都要執行一次。在關聯子查詢中是信息流是雙向的。外部查詢的每行數據傳遞一個值給子查詢,然后子查詢為每一行數據執行一次並返回它的記錄。然后,外部查詢根據返回的記錄做出決策。

 反正我是沒看懂,下面詳細解釋SQL中關聯子查詢的邏輯。

二、舉例

員工表的主要信息:

要解決的問題:檢索工資大於同職位的平均工資的員工信息。

2.1 直覺的做法

員工多,而相應的職位(如銷售員、經理、部門經理等)少,因此首先想到的思路對職位分組,這樣就能分別得到各個職位的平均工資,再比較每個人的工資和他對應職位的平均工資,大於則被篩選出來。

首先得到各個職位的平均工資

代碼如下:

1 select job,avg(sal) from emp
2 group by job;

結果如下:

然后利用子查詢,對他們進行對比(幻想)

代碼如下:

1 select * from emp where sal >
2 (select avg(sal) from emp
3 group by job);

但是子表查詢結果是5行,因此這段代碼根本無法執行。

2.2 正確的做法

正確的做法是使用關聯子查詢。代碼如下。

1 select * from emp e where sal > 
2 (select avg(sal) from emp where job = e.job);

執行邏輯是這樣

 

第一步

先執行外層查詢,即先執行:

1 select * from emp e;

結果是:

 

 也就是該表的所有內容。又因為子查詢中連接了這個表本身(where job = e.job ),所以將第一條記錄轉到子查詢。

第二步

這條進入子查詢后,子查詢job是CLERK,所以先篩選出所有Job=‘CLERK’的,再對他們取平均。

相當於執行了:

1 select avg(sal) from emp where job='CLERK';

結果是

 

第三步

這個結果進入外層查詢where和SMITH這個人的sal進行對比,相當於執行

select * from emp where sal>1037.5 and job='CLERK';

結果是為:

 

循環

然后就抽出第一次外層查詢的第二條(ALLEN):

 

繼續如上第一、二、三部。

重復計算嗎?

每條記錄都執行,第二行的ALLEN和第三行的WARD都是SALESMAN(銷售人員),那么他們在子查詢中會重復計算一次平均工資進行比較。這樣會不會設計重復計算?答案是不會,效率並沒有降低,SQL已經對此進行過優化。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM