資料庫設計遵循第三正規化 (3NF) 後,資料分散於多張關聯表,查詢需透過 JOIN 重組。本文系統整理 INNER JOIN、LEFT/RIGHT/FULL OUTER JOIN、CROSS JOIN 五大類型語法、語意差異、適用場景與效能建議,並說明為何推薦 FROM 子句寫法而非舊式 WHERE 聯接。
SELECT A.SYMBOL, A.SNAME, B.TDATE, B.CLOSE
FROM SECURITYCODE A, DAYQUOTE B
WHERE A.SYMBOL = B.SYMBOL
AND B.TDATE >= A.LISTDATE
AND A.SYMBOL LIKE '600%';
缺點:聯接條件與篩選條件混雜、難以閱讀、外聯接語法 (*=, =*) 易產生歧義且已棄用。
SELECT A.SYMBOL, A.SNAME, B.TDATE, B.CLOSE
FROM SECURITYCODE A
INNER JOIN DAYQUOTE B ON A.SYMBOL = B.SYMBOL
WHERE B.TDATE >= A.LISTDATE
AND A.SYMBOL LIKE '600%'
ORDER BY A.SYMBOL, B.TDATE;
優點:聯接邏輯與篩選邏輯分離、支援完整外聯接語法、可讀性與維護性佳。
| 類型 | 關鍵字 | 回傳資料列 | 典型用途 | Venn 圖 |
|---|---|---|---|---|
| 內聯接 | INNER JOIN / JOIN | 雙方皆符合條件的列 | 主從表必然關聯 (訂單-明細) | 交集 |
| 左外聯接 | LEFT JOIN / LEFT OUTER JOIN | 左表所有列 + 右表匹配列 (無匹配則 NULL) | 主表保留、從表可選 (客戶-訂單) | 左圓完整 |
| 右外聯接 | RIGHT JOIN / RIGHT OUTER JOIN | 右表所有列 + 左表匹配列 | 左外聯接反向,鮮用 | 右圓完整 |
| 完整外聯接 | FULL JOIN / FULL OUTER JOIN | 雙表所有列,無匹配處填 NULL | 雙向保留、差異比對 (對帳) | 聯集 |
| 交叉聯接 | CROSS JOIN | 笛卡兒積 (左列數 × 右列數) | 產生組合矩陣、測試資料生成 | 無重疊 |
外聯接中,ON 子句條件決定「如何匹配」,WHERE 子句條件決定「最終保留哪些列」。
-- 正確:篩選條件放在 ON,保留左表所有列
SELECT S.STOR_ID, S.QTY, T.TITLE
FROM SALES S
RIGHT JOIN TITLES T ON S.TITLE_ID = T.TITLE_ID AND S.QTY > 50;
-- 錯誤:放在 WHERE 會過濾掉右表無匹配列 (變成內聯接)
SELECT S.STOR_ID, S.QTY, T.TITLE
FROM SALES S
RIGHT JOIN TITLES T ON S.TITLE_ID = T.TITLE_ID
WHERE S.QTY > 50; -- 導致 NULL 被過濾
FULL JOIN,資料量爆炸;改用 UNION ALL 分別查再合併。CROSS JOIN 僅用於小表 (如設定表、日期維度) 或刻意產生組合。| 反模式 | 問題 | 修正 |
|---|---|---|
| WHERE 子句聯接 + *= 語法 | 舊語法、易產生歧義、不支援 FULL JOIN | 改用 FROM ... LEFT JOIN |
| LEFT JOIN 後 WHERE 右表欄位 = 值 | 隱性轉為 INNER JOIN | 條件移至 ON 子句 |
| 大量 CROSS JOIN 產生中繼結果 | TempDB 爆滿、記憶體壓力 | 改用 APPLY / 窗口函數 / 分批處理 |