首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL LEFT JOIN 查詢差集:找出主表存在但從表不存在的資料

     編輯:MySQL 資料庫相關知識

MySQL LEFT JOIN 查詢差集:找出主表存在但從表不存在的資料


業務場景

抽獎系統:enet_wall_list 記錄所有參與用戶(同一用戶可能多條),enet_wall_lottery 記錄中獎用戶。需求:**找出所有未中獎用戶(去重)**。


核心 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:以左表(l)為基準,右表(lottery)匹配成功則帶入欄位,**匹配失敗則所有右表欄位填 NULL**。
  2. WHERE lottery.id IS NULL:過濾掉有匹配成功的行,保留**右表完全無對應記錄**的左表行 → 即差集。
  3. DISTINCT / GROUP BY:左表可能有重複 openid,去重得到唯一用戶清單。

通用範本:兩表差集查詢

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。
  • WHERE b.key IS NULL:精準過濾「右表無對應」的行。
  • LENGTH(str):計算字串長度(位元組),可用於過濾異常資料。

替代方案對比

方法SQL 範例優點缺點
LEFT JOIN + IS NULL如上標準 SQL、可攜性強、可直接選左表任意欄位大表需注意索引
NOT EXISTSSELECT * FROM A WHERE NOT EXISTS (SELECT 1 FROM B WHERE B.pid=A.pid)語意清晰、優化器常能轉為 Anti-Join、不產生中間結果集舊版 MySQL 優化較弱
NOT INSELECT * FROM A WHERE pid NOT IN (SELECT pid FROM B)簡潔**子查詢含 NULL 會導致全表掃描且結果為空**,極度不推薦
EXCEPT (MINUS)SELECT pid FROM A EXCEPT SELECT pid FROM B集合運算語意明確MySQL **不支援** EXCEPT(MariaDB 10.3+ 支援)

索引建議

  • **連接欄位雙向建索引**:ALTER TABLE A ADD INDEX idx_pid (pid); ALTER TABLE B ADD INDEX idx_pid (pid);
  • **覆蓋索引**:若只查 pid,單欄索引即為覆蓋索引,避免回表。
  • **條件下推**:WHERE A.weid=63 應有索引 idx_weid (weid) 或複合 idx_weid_pid (weid, pid)。

擴展:多欄位關聯差集

SELECT a.*
FROM `A` a
LEFT JOIN `B` b ON a.col1 = b.col1 AND a.col2 = b.col2
WHERE b.col1 IS NULL;

複合連接條件同理,右表任一關鍵欄位為 NULL 即表示無匹配。

掌握 LEFT JOIN + IS NULL 模式,是處理「存在性否定」查詢的標準利器,配合正確索引可支撐千萬級資料量秒級回應。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved