| 類型 | 關鍵字 | 語意 | 典型用途 |
|---|---|---|---|
| 交叉聯結 | CROSS JOIN | 笛卡兒積 (所有組合) | 測試資料生成、矩陣運算 |
| 內部聯結 | [INNER] JOIN | 雙邊符合條件的列 | 最常用,主從表關聯 |
| 左外部聯結 | LEFT [OUTER] JOIN | 左表全保留,右表無配對填 NULL | 主表帶明細、報表列表 |
| 右外部聯結 | RIGHT [OUTER] JOIN | 右表全保留,左表無配對填 NULL | 較少用,可改 LEFT JOIN 交換順序 |
| 完整外部聯結 | FULL [OUTER] JOIN | 雙邊全保留,無配對填 NULL | 雙向差異比對、資料核對 |
| 自我聯結 | JOIN 同一表別名 | 表內部行與行比較 | 階層結構、同事入職日期比對 |
-- 寫法 A:ON 中混合聯結與篩選
SELECT a.cust_id, b.order_date, b.tot_amt
FROM customer a LEFT JOIN sales b
ON a.cust_id = b.cust_id AND b.order_date > '1996/10/15';
-- 寫法 B:衍生表預先篩選 (推薦,減少外部聯結後再篩選)
SELECT a.cust_id, b.order_date, b.tot_amt
FROM customer a
LEFT JOIN (SELECT * FROM sales WHERE order_date > '1996/10/15') b
ON a.cust_id = b.cust_id;
SELECT a.emp_no, a.emp_name, b.emp_no, b.emp_name, a.date_hired
FROM employee a JOIN employee b
ON a.emp_no <> b.emp_no AND a.date_hired = b.date_hired
WHERE a.emp_name > b.emp_name; -- 只取一邊,消除鏡像重複
-- 表:id, ic, name, amount (ic='i' 收入, 'c' 支出)
-- 目標:收入與支出按序號並排
SELECT aaa.*, bbb.*
FROM (
SELECT (SELECT COUNT(id) FROM aa b WHERE b.id < a.id AND ic='i') AS seq, *
FROM aa a WHERE ic='i'
) aaa
FULL JOIN (
SELECT (SELECT COUNT(id) FROM aa b WHERE b.id < a.id AND ic='c') AS seq, *
FROM aa a WHERE ic='c'
) bbb ON aaa.seq = bbb.seq
ORDER BY aaa.name;
USE pubs;
SELECT SUBSTRING(RTRIM(a.au_fname)+' '+LTRIM(a.au_lname),1,25) AS Name,
SUBSTRING(t.title,1,20) AS Title
FROM authors a
INNER MERGE JOIN titleauthor ta ON a.au_id = ta.au_id
INNER HASH JOIN titles t ON t.title_id = ta.title_id
ORDER BY au_lname, au_fname;
實務建議:
1. 習慣用 LEFT JOIN 統一風格,避免 RIGHT JOIN 造成閱讀困擾。
2. 外部聯結的篩選條件**盡量放在 ON 子句**,而非 WHERE,否則隱性轉為內部聯結。
3. 大表聯結前確認聯結欄位有索引,觀察 Execution Plan 確認運算子 (Nested Loops / Merge / Hash)。