SQL關聯子查詢的詳解

我們先來看一下SQL關聯子查詢的基本邏輯的定義
對於外部查詢返回的每一行數據,內部查詢都要執行一次。在關聯子查詢中是信息流是雙向的。外部查詢的每行數據傳遞一個值給子查詢,然後子查詢爲每一行數據執行一次並返回它的記錄。然後,外部查詢根據返回的記錄做出決策。

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

有一張員工表,它的主要信息爲:
在這裏插入圖片描述
要解決的問題:檢索工資大於同職位的平均工資的員工信息。

一般我們會這樣想:

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

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

代碼如下:

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

結果如下:
在這裏插入圖片描述
然後利用子查詢,對他們進行對比(幻想)

代碼如下

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

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

正確的做法應該是用關聯子查詢

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

第一步
先執行外層查詢,即先執行:

select * from emp e;

在這裏插入圖片描述
也就是該表的所有內容。又因爲子查詢中連接了這個表本身(where job = e.job ),所以將第一條記錄轉到子查詢。
在這裏插入圖片描述
第二步
這條進入子查詢後,子查詢job是CLERK,所以先篩選出所有Job=‘CLERK’的,再對他們取平均。

相當於執行了:

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已經對此進行過優化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章