MySQL 左連接搭配 WHERE 條件時,常會踩到「條件寫在 ON vs WHERE 結果不同」的坑。本文透過實例解析差異,並完整補充內連接、左連接、右連接、全連接的行為差異。
SELECT * FROM _test a
LEFT JOIN _test b ON a.id = b.id
WHERE a.level = '20' AND a.month = '04'
AND b.level = '20' AND b.month = '03';
因為右表 b 的條件寫在 WHERE,若右表無匹配行,b.level 為 NULL,條件不成立,導致左表資料也被過濾掉,實際變成內連接。
SELECT a.*, b.*
FROM (SELECT * FROM _test WHERE level = '20' AND month = '04') AS a
LEFT JOIN (SELECT * FROM _test WHERE level = '20' AND month = '03') AS b
ON a.id = b.id;
子查詢先過濾,再做左連接,才能保留左表所有符合條件的資料,右表無匹配時顯示 NULL。
假設兩表:
T1 (userid, username, password)
1, jack, jackpwd
2, owen, owenpwd
T2 (userid, jifen, dengji)
1, 20, 3
3, 50, 6
SELECT * FROM T1 INNER JOIN T2 ON T1.userid = T2.userid;
結果:僅保留雙方都有的 userid=1。
SELECT * FROM T1 LEFT OUTER JOIN T2 ON T1.userid = T2.userid;
結果:T1 全部保留,T2 無匹配處為 NULL(userid=2 的 owen 保留)。
SELECT * FROM T1 RIGHT OUTER JOIN T2 ON T1.userid = T2.userid;
結果:T2 全部保留,T1 無匹配處為 NULL(userid=3 的行保留)。
SELECT * FROM T1 FULL OUTER JOIN T2 ON T1.userid = T2.userid;
結果:左右表全部保留,去重合併(MySQL 不直接支援,可用 UNION 模擬)。
INNER JOIN 效率最高,優先使用WITH 子句)或子查詢預先過濾