業務場景:抽獎活動中,wall_list 記錄所有參與用戶(含重複),wall_lottery 記錄中獎用戶。需找出未中獎的所有用戶(去重)。傳統 WHERE 多表關聯在右表為空時回傳空集,LEFT JOIN 則完美解決。
SELECT DISTINCT l.openid
FROM `enet_wall_list` AS l
LEFT JOIN `enet_wall_lottery` AS lottery
ON l.openid = lottery.openid
WHERE l.weid = 63
AND lottery.id IS NULL;
LEFT JOIN 保證左表(wall_list)每一行至少出現一次。openid,其所有欄位(含 id)均為 NULL。lottery.id IS NULL 精準鎖定「左表有、右表無」的行。GROUP BY l.openid 或 DISTINCT 消除參與記錄重複。SELECT a.*
FROM `A` a
LEFT JOIN `B` b ON a.pid = b.pid
WHERE b.pid IS NULL
AND LENGTH(a.pid) < 10; -- 額外業務過濾
LEFT JOIN ... ON:左表為驅動表,右表無匹配以 NULL 填充。LENGTH(str):回傳字串位元組長度(非字元數),中文 UTF-8 下 1 字 = 3 位元組。CHAR_LENGTH()。openid/pid)在兩表均有索引。Full Scan + Hash Join(MySQL 8.0+),仍需索引支援 IS NULL 過濾。ON 條件使用函數(如 TRIM()),導致索引失效。SELECT DISTINCT l.openid
FROM `enet_wall_list` l
WHERE l.weid = 63
AND NOT EXISTS (
SELECT 1 FROM `enet_wall_lottery` lottery
WHERE lottery.openid = l.openid
);
語義更直觀,MySQL 8.0+ 優化器會自動轉為 ANTI JOIN,效能與 LEFT JOIN ... IS NULL 相當;舊版本建議用 LEFT JOIN。
掌握 LEFT JOIN ... IS NULL 模式,即可輕鬆處理「差集」、「孤兒資料」、「缺失關聯」等常見業務查詢。