SQL Server 2005 引入 EXCEPT (差集) 與 INTERSECT (交集) 集合運算子,提供比 NOT IN/NOT EXISTS 更直觀、正確處理 NULL 值的集合運算方式。本文詳細說明語法規則、NULL 處理差異、優先順序、SELECT INTO 限制、ORDER BY 規則,並附 SQL 2000 替代寫法對比。
| 運算子 | 語意 | 對應邏輯 |
|---|---|---|
EXCEPT | 左邊有、右邊無 | A \ B (差集) |
INTERSECT | 左右都有 | A ∩ B (交集) |
DISTINCT (類似 UNION)EXCEPT/INTERSECT 視 NULL = NULL,不同於 =、IN、JOIN (NULL ≠ NULL)INTERSECT > EXCEPT > UNION (左至右同級)CREATE TABLE TableA (col1 INT);
INSERT INTO TableA VALUES (1),(1),(2),(3),(4),(4),(5),(NULL),(NULL);
CREATE TABLE TableB (col2 INT);
INSERT INTO TableB VALUES (NULL),(1),(2),(3);
CREATE TABLE TableC (col3 INT);
INSERT INTO TableC VALUES (1),(5),(6);
SELECT col1 FROM TableA
EXCEPT
SELECT col3 FROM TableC;
col1
----
NULL
2
3
4
關鍵:NULL出現在結果中,因EXCEPT視 NULL 相等,TableA 有 NULL、TableC 無 NULL → NULL 被保留。
SELECT col1 FROM TableA a
WHERE NOT EXISTS (SELECT col3 FROM TableC WHERE a.col1 = col3)
GROUP BY col1;
結果相同 (含 NULL)。
SELECT col1 FROM TableA
WHERE col1 NOT IN (SELECT col3 FROM TableC)
GROUP BY col1;
col1
----
2
3
4
原因:NOT IN內部轉為NOT (col1 = val1 OR col1 = val2 ...),若子查詢含 NULL,col1 = NULL為 UNKNOWN,整個NOT (TRUE OR UNKNOWN)為 UNKNOWN,該列被過濾。含 NULL 子查詢絕對不可用 NOT IN。
SELECT col1 FROM TableA
EXCEPT
SELECT col2 FROM TableB
INTERSECT
SELECT col3 FROM TableC;
等價於:TableA EXCEPT (TableB INTERSECT TableC)
col1
----
NULL
2
3
4
5
TableB ∩ TableC = {1},TableA \ {1} = {NULL,2,3,4,5}
SELECT col1 INTO #tem FROM TableA
EXCEPT
SELECT col3 FROM TableC;
SELECT * FROM #tem;
DROP TABLE #tem;
SELECT col1 FROM TableA
INTERSECT
SELECT col3 FROM TableC
ORDER BY col1; -- 必須用左邊查詢的欄位名/別名
col1
----
1
5
EXCEPT/INTERSECT,語意清晰、NULL 語意正確(A EXCEPT B) INTERSECT CEXCEPT ALL/INTERSECT ALL (SQL 2005 不支援,需 ROW_NUMBER() 模擬)NOT IN 子查詢是否含 NULL,改用 NOT EXISTS 或 EXCEPT