| Join 類型 | 結果集 | 口訣 |
|---|---|---|
| INNER JOIN | 雙方**都匹配**的行 | 交集 |
| LEFT JOIN | 左表**全部** + 右表匹配行(無則 NULL) | 左全右部 |
| RIGHT JOIN | 右表**全部** + 左表匹配行(無則 NULL) | 右全左部 |
MySQL 解析器將 RIGHT JOIN 內部轉換為 LEFT JOIN(交換表順序)。**建議統一使用 LEFT JOIN**,可讀性更好、避免混淆。
-- 等價轉換
SELECT * FROM A RIGHT JOIN B ON A.id = B.id;
-- 等同於
SELECT * FROM B LEFT JOIN A ON B.id = A.id;
-- 表 A
+------+-----------+
| aID | aNum |
+------+-----------+
| 1 | a20050111 |
| 2 | a20050112 |
| 3 | a20050113 |
| 4 | a20050114 |
| 5 | a20050115 |
+------+-----------+
-- 表 B
+------+------------+
| bID | bName |
+------+------------+
| 1 | 2006032401 |
| 2 | 2006032402 |
| 3 | 2006032403 |
| 4 | 2006032404 |
| 8 | 2006032408 |
+------+------------+
SELECT * FROM A LEFT JOIN B ON A.aID = B.bID;
+------+-----------+------+------------+
| aID | aNum | bID | bName |
+------+-----------+------+------------+
| 1 | a20050111 | 1 | 2006032401 |
| 2 | a20050112 | 2 | 2006032402 |
| 3 | a20050113 | 3 | 2006032403 |
| 4 | a20050114 | 4 | 2006032404 |
| 5 | a20050115 | NULL | NULL | -- A 有、B 無 → NULL
+------+-----------+------+------------+
SELECT * FROM A RIGHT JOIN B ON A.aID = B.bID;
+------+-----------+------+------------+
| aID | aNum | bID | bName |
+------+-----------+------+------------+
| 1 | a20050111 | 1 | 2006032401 |
| 2 | a20050112 | 2 | 2006032402 |
| 3 | a20050113 | 3 | 2006032403 |
| 4 | a20050114 | 4 | 2006032404 |
| NULL | NULL | 8 | 2006032408 | -- B 有、A 無 → NULL
+------+-----------+------+------------+
SELECT * FROM A INNER JOIN B ON A.aID = B.bID;
-- 等同舊寫法:SELECT * FROM A, B WHERE A.aID = B.bID;
+------+-----------+------+------------+
| aID | aNum | bID | bName |
+------+-----------+------+------------+
| 1 | a20050111 | 1 | 2006032401 |
| 2 | a20050112 | 2 | 2006032402 |
| 3 | a20050113 | 3 | 2006032403 |
| 4 | a20050114 | 4 | 2006032404 |
+------+-----------+------+------------+
SELECT p.price, pd.name, m.manufacturers_name
FROM products p
LEFT JOIN products_description pd ON p.products_id = pd.products_id
LEFT JOIN manufacturers m ON p.manufacturers_id = m.manufacturers_id;
執行順序: 先 p LEFT JOIN pd 產生中間結果,再 LEFT JOIN m。括號決定關聯順序。
-- 錯誤:WHERE 過濾會將 LEFT JOIN 退化為 INNER JOIN
SELECT * FROM A LEFT JOIN B ON A.id = B.id WHERE B.name = 'test';
-- 正確:右表條件放在 ON 中,保留 LEFT JOIN 語義
SELECT * FROM A LEFT JOIN B ON A.id = B.id AND B.name = 'test';
原則: 右表的過濾條件寫在 ON,左表的過濾條件寫在 WHERE。
SELECT *,只查需要欄位STRAIGHT_JOIN 強制順序或改寫為子查詢