LEFT JOIN 與 RIGHT JOIN 是外連接的兩種形式,核心差異在於**保留哪一側表的所有行**。本文以實戰範例詳細解析語法、執行流程、IS NULL 反向查詢模式、與 INNER JOIN 的效能差異,並給出優化建議。
SELECT a.aid, a.title, u.username FROM article AS a LEFT JOIN user AS u ON a.uid = u.uid;
NULL。article LEFT OUTER JOIN user。WHERE 過濾後的左表結果集)。ON 條件在右表尋找匹配 (利用右表索引)。NULL 輸出。article 表: aid | title | uid 1 | 'Hello' | 1 2 | 'World' | 2 3 | 'Foo' | 3 4 | 'Orphan' | 99 (user 無 uid=99) user 表: uid | username 1 | 'Alice' 2 | 'Bob' 3 | 'Charlie' 查詢結果: aid | title | username 1 | Hello | Alice 2 | World | Bob 3 | Foo | Charlie 4 | Orphan | NULL -- 關鍵:左表保留,右表 NULL
SELECT a.aid, a.title FROM article a LEFT JOIN user u ON a.uid = u.uid WHERE u.uid IS NULL; -- 右表主鍵為 NULL 即無匹配
**注意**:必須判斷右表**主鍵或非空唯一鍵**為 NULL,不可判斷可空欄位 (可能資料本身為 NULL)。
SELECT a.aid, a.title, u.username FROM article a RIGHT JOIN user u ON a.uid = u.uid;
NULL。LEFT JOIN 互換:A RIGHT JOIN B ≡ B LEFT JOIN A。aid | title | username 1 | Hello | Alice 2 | World | Bob 3 | Foo | Charlie NULL| NULL | David -- 右表保留,左表 NULL (假設 user 有 uid=4 David)
SELECT u.username FROM article a RIGHT JOIN user u ON a.uid = u.uid WHERE a.aid IS NULL;
| 連接類型 | 結果集大小 | 優化器選擇 |
|---|---|---|
INNER JOIN | 較小 (僅匹配行) | 優先選擇,可交換驅動表順序 |
LEFT/RIGHT JOIN | 較大 (含保留側所有行) | 驅動表固定為保留側,優化空間較小 |
**建議**:若業務邏輯確定兩側必有匹配 (如外鍵關係且無孤兒資料),**改用 INNER JOIN** 讓優化器自由選擇最佳驅動表。
ON a.uid = u.uid → user.uid 有索引)。WHERE 過濾欄位有索引可減少驅動行數。SELECT 欄位可避免回表 (Using index)。-- 錯誤:WHERE 條件過濾右表,導致外連接退化為內連接 SELECT * FROM article a LEFT JOIN user u ON a.uid = u.uid WHERE u.status = 1; -- u.status=1 會過濾掉 u 為 NULL 的行 -- 正確:將右表條件移至 ON 子句 SELECT * FROM article a LEFT JOIN user u ON a.uid = u.uid AND u.status = 1;
SELECT a.title, u.username, c.name AS category FROM article a LEFT JOIN user u ON a.uid = u.uid LEFT JOIN category c ON a.cid = c.cid WHERE a.status = 1;
-- 1. LEFT JOIN + IS NULL (經典) SELECT u.* FROM user u LEFT JOIN article a ON u.uid = a.uid WHERE a.aid IS NULL; -- 2. NOT EXISTS (語意清晰、短路) SELECT u.* FROM user u WHERE NOT EXISTS (SELECT 1 FROM article a WHERE a.uid = u.uid); -- 3. NOT IN (注意 NULL 陷阱) SELECT u.* FROM user u WHERE u.uid NOT IN (SELECT uid FROM article WHERE uid IS NOT NULL);
**效能**:MySQL 5.6+ 半連接優化下,三者通常同樣執行計畫 (type=ref, Extra=Using index),推薦 NOT EXISTS 或 LEFT JOIN。
結語: LEFT JOIN 是外連接的標準寫法,配合 IS NULL 反向查詢解決「缺失關聯」問題。核心優化點:**被驅動表關聯欄位建索引、右表條件寫在 ON 不寫在 WHERE、業務允許時優先 INNER JOIN**。掌握這三點,外連接不再是效能黑盒。