首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL JOIN 條件放在 ON 還是 WHERE?左連接過濾邏輯深度解析

     編輯:關於SqlServer

問題場景

使用視圖關聯多表時,需求:左表所有資料必須顯示,右表僅顯示符合特定條件(如 years=2010)的資料,不符合則顯示 NULL。直接在 WHERE 子句過濾右表欄位會導致左連接退化為內連接,資料遺失。

錯誤示範:WHERE 過濾右表

SELECT *
FROM table1 AS a
LEFT JOIN table2 AS b ON a.tid = b.tid
WHERE a.parentid = '' AND b.years = 2010;  -- 錯誤!b.years=NULL 的行被過濾掉

結果:b.years = 2010 在 WHERE 中評估為 UNKNOWN(因 NULL = 2010 為 UNKNOWN),導致左表無對應右表資料的行被排除,實際變成內連接。

正確寫法:ON 子句中過濾右表

SELECT *
FROM table1 AS a
LEFT JOIN table2 AS b ON a.tid = b.tid AND b.years = 2010  -- 正確!
WHERE a.parentid = '';

差異本質:

  • ON 條件決定如何關聯:右表先依條件過濾,再與左表關聯;無匹配則右表欄位補 NULL
  • WHERE 條件決定最終保留哪些行:在關聯完成後過濾,NULL 值不通過任何比較運算子

執行邏輯時序圖解

  1. FROM / JOIN:產生虛擬表(含外部連接補 NULL)
  2. ON:套用關聯條件(外部連接保留左表所有行)
  3. WHERE:套用篩選條件(移除不符合行)
  4. GROUP BY / HAVING:分組與聚合篩選
  5. SELECT / ORDER BY:投影與排序

進階模式:子查詢預先過濾右表

複雜條件或效能考量時,可先過濾右表再關聯:

SELECT *
FROM table1 AS a
LEFT JOIN (
    SELECT * FROM table2 WHERE years = 2010
) AS b ON a.tid = b.tid
WHERE a.parentid = '';

此寫法語意最清晰、最易維護,且優化器通常能產生相同執行計畫。

快速判斷口訣

左連接保左表,右表條件寫 ON 邊;
WHERE 只篩左表欄,右表條件別亂牽。

驗證查詢

-- 對比兩種寫法的執行計畫與結果集行數
SET STATISTICS IO ON;
SET STATISTICS TIME ON;

-- 寫法 A:WHERE 過濾右表
SELECT COUNT(*) FROM table1 a LEFT JOIN table2 b ON a.tid=b.tid WHERE b.years=2010;

-- 寫法 B:ON 過濾右表
SELECT COUNT(*) FROM table1 a LEFT JOIN table2 b ON a.tid=b.tid AND b.years=2010;
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved