萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL LEFT JOIN 實現差集查詢:找出「存在於 A 但不在 B」的資料

業務場景:抽獎活動中,wall_list 記錄所有參與用戶(含重複),wall_lottery 記錄中獎用戶。需找出未中獎的所有用戶(去重)。傳統 WHERE 多表關聯在右表為空時回傳空集,LEFT JOIN 則完美解決。

核心 SQL

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;

關鍵點解析

  1. 左表為主: LEFT JOIN 保證左表(wall_list)每一行至少出現一次。
  2. 右表無匹配 → NULL: 若右表無對應 openid,其所有欄位(含 id)均為 NULL。
  3. 過濾條件: lottery.id IS NULL 精準鎖定「左表有、右表無」的行。
  4. 去重: GROUP BY l.openid 或 DISTINCT 消除參與記錄重複。

通用範本:A 表存在、B 表不存在

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()),導致索引失效。

延伸:NOT EXISTS 寫法

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 模式,即可輕鬆處理「差集」、「孤兒資料」、「缺失關聯」等常見業務查詢。

copyright © 萬盛學電腦網 all rights reserved