CodeGym /課程 /SQL SELF /什麼是巢狀查詢,它們有什麼用?

什麼是巢狀查詢,它們有什麼用?

SQL SELF
等級 13 , 課堂 0
開放

現在你已經準備好進入下一步 —— 在 SQL 裡玩玩 巢狀查詢 了。今天我們會聊聊這到底是什麼、為什麼要用、巢狀查詢有哪些類型,還有它們在現實生活中到底有多實用。

巢狀查詢(或子查詢)就是那種會被放在其他 SQL 查詢裡的 SQL 查詢。有點像俄羅斯娃娃或高麗菜:外面有個主查詢,裡面藏著另一個比較小的查詢。子查詢會先執行,然後它的結果會被外面的主查詢拿來用(有時候主查詢也會被叫做「主要查詢」)。

我們來看個例子:

範例 1:它怎麼運作

我們有一個 students 資料表,裡面有這些資料:

id 名字 年齡 群組_id
1 愛麗絲 20 1
2 鮑勃 22 2
3 克拉克 21 1
4 迪娜 23 3
5 艾蜜莉亞 22 2

還有一個 groups 資料表,裡面存著群組名稱:

id 名稱
1 數學班
2 物理班
3 文學班

如果我們想知道有哪些群組裡有學生在讀,可以用巢狀查詢:

SELECT 名稱
FROM groups 
WHERE id IN (
    SELECT 群組_id 
    FROM students 
    WHERE 年齡 > 21
);

這裡發生了什麼?

巢狀查詢:

SELECT 群組_id 
FROM students 
WHERE 年齡 > 21

這個查詢會選出所有年齡大於 21 歲學生的 群組_id。結果會是一個群組 id 的清單,比如 [2, 3]

主查詢:

SELECT 名稱 
FROM groups 
WHERE id IN ([子查詢結果])

這個查詢會用子查詢的結果,回傳 id 是 2 或 3 的群組名稱。

結果:

物理班
文學班

還是看不懂?很正常啦。別擔心,等等我們會慢慢拆解。

先從一個簡單的想法開始 —— SELECT 查詢的結果,其實就是一個 虛擬資料表。 它有欄位、有列,不就是資料表嗎?

既然查詢結果是資料表,那你就可以在 JOIN 或更複雜的語法裡用它,就像用真的資料表一樣。

它沒有名字,這有點麻煩。但欄位運算式也沒名字,我們都會給它們 alias(別名)。虛擬資料表也可以這樣搞。

更多細節下次再說 —— 先不爆雷 :P

巢狀查詢的好處

  1. 它們讓複雜的問題變簡單。有時候一個資料表沒辦法給你所有你想要的資訊。子查詢可以把查詢拆成兩步:先拿到中間結果,再用它來拿最終資料。

  2. 處理中間結果。巢狀查詢很適合你需要先做點額外運算再處理資料的時候。比如找最小值或算總和。

  3. 讓程式碼更好讀。巢狀查詢讓你的 SQL 更有結構,特別是當你面對大資料表和複雜邏輯時。

巢狀查詢的主要類型

巢狀查詢可以用在 SQL 查詢的不同地方。根據你寫在哪裡,可以分成幾種。

  1. 寫在 SELECT 裡的子查詢。子查詢會放在欄位清單裡,用來算 。這很方便,比如你想在結果裡加一個新欄位。

範例 —— 加一個欄位,顯示學生的最大年齡:

SELECT 名字, 年齡,
       (SELECT MAX(年齡) FROM students) AS 最大年齡 
FROM students;

結果:

名字 年齡 最大年齡
愛麗絲 20 23
鮑勃 22 23
克拉克 21 23
迪娜 23 23
艾蜜莉亞 22 23
  1. 寫在 FROM 裡的子查詢。子查詢會被當成暫時的資料表。如果你要先聚合或轉換資料,這超好用。

範例 —— 算每個群組學生的平均年齡:

SELECT tmp.群組_id, tmp.平均年齡
FROM (
    SELECT 群組_id, AVG(年齡) AS 平均年齡
    FROM students
    GROUP BY 群組_id
) AS tmp -- 給暫時資料表取個別名 tmp 
WHERE tmp.平均年齡 > 21;

結果:

群組_id 平均年齡
2 22.0
3 23.0
  1. 寫在 WHEREHAVING 裡的子查詢。子查詢可以當條件來過濾資料列。這很常用來檢查
  2. 有沒有資料存在,或是比較數值。

範例 —— 找出年齡大於平均年齡的學生:

SELECT 名字, 年齡
FROM students
WHERE 年齡 > (
    SELECT AVG(年齡) 
    FROM students
);

結果:

名字 年齡
鮑勃 22
迪娜 23
艾蜜莉亞 22

用巢狀查詢的優點

彈性更高:巢狀查詢讓你可以處理更複雜的資料結構。

把問題拆步驟:你可以把邏輯拆成子查詢,讓 SQL 更好懂。

隨時處理中間資料:你可以「即時」處理資料,不用在資料庫裡建暫時資料表。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION