SQL 中的嵌套查詢

SQL 語言允許您將一個查詢嵌套在另一個查詢中。這使得編寫一個非常大的查詢成為可能,該查詢將執行大型和復雜的操作,儘管代碼的可讀性大大降低。

根據子查詢返回的值的多少,它們可以應用的區域會發生變化。一共有三個選項:

  • 子查詢返回一個單一值(一列和一行)。
  • 子查詢返回一個值列表(一個只有一列的表)。
  • 子查詢返回一個表(許多列,任意數量的行)。

讓我們看一下每種情況的一個例子。

帶有標量結果的子查詢

讓我們從員工表中找出薪水高於公司平均水平的所有員工的列表。我們該怎麼做?

如果我們事先知道,我們可以通過將他們的工資與平均工資進行比較來輕鬆過濾員工。同時,我們已經編寫了一個查詢,可以讓我們計算公司員工的平均工資。讓我們記住它:

SELECT AVG(salary) FROM employee 

然後 MySQL 返回值:76833.3333

現在如何找到工資高於平均水平的所有員工的列表?這也很簡單:

 SELECT * FROM employee 
   WHERE salary > 76833.3333 

此查詢的結果將是:

ID 姓名 職業 薪水
1個 伊万諾夫伊万 程序員 100000
2個 彼得羅夫彼得 程序員 80000
4個 拉比諾維奇·莫伊沙 導演 200000

現在我們只需用第一個請求代替值 76833 來合併兩個請求:

   SELECT * FROM employee 
   WHERE salary > (SELECT AVG(salary) FROM employee) 

此查詢的結果將是相同的:

ID 姓名 職業 薪水
1個 伊万諾夫伊万 程序員 100000
2個 彼得羅夫彼得 程序員 80000
4個 拉比諾維奇·莫伊沙 導演 200000

帶有值列表的子查詢

你還記得我們曾經有過一個任務——從一個表中找到所有在另一個表中沒有對應記錄的記錄嗎?

還有這張圖:

如果我沒記錯的話,任務如下:顯示員工表中沒有任務的所有員工的列表

讓我們也分兩步找到解決方案。

首先,讓我們編寫一個查詢,返回在任務表中有任務的所有員工的 ID。只要記住兩件事:

  • 刪除重複項 - 使用 DISTINCT 關鍵字。
  • 從結果中移除 NULL 值。
SELECT DISTINCT employee_id FROM task 
   WHERE employee_id IS NOT NULL

在這裡,我們得到了這樣一個請求的漂亮結果:

員工ID
1個
2個
5個
4個
6個

為了方便,我們暫時記為一個序列:1,2,5,4,6。現在讓我們編寫第二個查詢 - 到 employee 表,它將返回其 id 不包含在第一個列表中的員工列表:

SELECT * FROM employee  
WHERE id NOT IN (1,2,5,4,6)

這個查詢的結果是:

ID 姓名 職業 薪水 年齡 加入日期
3個 伊万諾夫謝爾蓋 測試儀 40000 三十 2014-01-01

現在,與前面的示例一樣,您可以通過簡單地替換第一個請求的主體而不是 id 列表來合併兩個請求。

 SELECT * FROM employee 
   WHERE id NOT IN ( 
      	SELECT DISTINCT employee_id FROM task 
      	WHERE employee_id IS NOT NULL 
   )