多表查詢是 SQL 核心技能。本文系統講解 UNION/INTERSECT/EXCEPT 聯合查詢 以及 CROSS/INNER/OUTER/NATURAL JOIN 連接查詢 的語法、差異、適用場景與效能考量。
將多個 SELECT 結果集垂直合併(行數增加,欄位數不變)。
SELECT 列表 FROM 表1
UNION [ALL]
SELECT 列表 FROM 表2
[UNION [ALL] SELECT 列表 FROM 表3 ...]
ORDER BY、LIMIT 僅能套用於最終結果,需用第一個 SELECT 的別名/位置UNION 去重(相當 DISTINCT),UNION ALL 保留所有行,效能較佳INTERSECT:交集(兩邊都有)EXCEPT:差集(左有右無)-- 有玩具的孩子
SELECT user_id FROM user INTERSECT SELECT user_id FROM toy;
-- 沒玩具的孩子
SELECT user_id FROM user EXCEPT SELECT user_id FROM toy;
橫向合併多表(欄位數增加),依據關聯條件匹配行。
無 ON 條件,表 A 每行與表 B 每行組合。A 有 m 行,B 有 n 行 → 結果 m×n 行。
SELECT u.username, t.toyname FROM user u CROSS JOIN toy t;
慎用:資料量大時極易撐爆記憶體。
僅保留雙方都滿足條件的行。
-- 等值連接(最常用)
SELECT u.username, t.toyname
FROM user u INNER JOIN toy t ON u.user_id = t.user_id;
-- 或 WHERE u.user_id = t.user_id
-- 非等值連接
SELECT u.username, t.toyname
FROM user u INNER JOIN toy t ON u.user_id <> t.user_id;
自動以同名欄位為連接條件。需確保同名欄位語義一致,否則易產生錯誤結果。
SELECT u.username, t.toyname FROM user u NATURAL JOIN toy t;
保留單側所有行,另一側無匹配則填 NULL。
-- 所有用戶及其玩具(無玩具顯示 NULL)
SELECT u.username, t.toyname
FROM user u LEFT JOIN toy t ON u.user_id = t.user_id;
-- 所有玩具及擁有者(無主玩具顯示 NULL)
SELECT u.username, t.toyname
FROM user u RIGHT JOIN toy t ON u.user_id = t.user_id;
注意:外連接的條件必須寫在 ON 子句,不能移到 WHERE,否則退化為內連接。
STRAIGHT_JOIN 強制順序)。