Answers:
EXCEPT
和之间有两个主要区别NOT IN
。
EXCEPT
过滤DISTINCT
左侧表中未出现在右侧表中的值。本质上与NOT EXISTS
with DISTINCT
子句相同。
它还希望两个表(或表中列的子集)在查询的左侧和右侧具有相同数量的列
例如,您不能执行以下操作:
SELECT ID, Name FROM TableA
EXCEPT
SELECT ID FROM TableB
这将导致错误:
使用UNION,INTERSECT或EXCEPT运算符组合的所有查询在其目标列表中必须具有相等数量的表达式。
NOT IN
不过滤DISTINCT
值,并返回左侧表中未出现在右侧表中的所有值。
NOT IN
要求您将一个表中的单个列与另一表或子查询中的单个列进行比较。
例如,如果您的子查询返回多个列:
SELECT * FROM TableA AS nc
WHERE ID NOT IN (SELECT ID, Name FROM TableB AS ec)
您会收到以下错误:
如果未使用EXISTS引入子查询,则只能在选择列表中指定一个表达式。
但是,如果右边的表中的包含NULL
由过滤的值中的NOT IN
,则返回一个空结果集,可能会产生意外结果。
CREATE TABLE #NewCustomers (ID INT);
CREATE TABLE #ExistingCustomers (ID INT);
INSERT INTO #NewCustomers
( ID )
VALUES
(8), (9), (10), (1), (3), (8);
INSERT INTO #ExistingCustomers
( ID )
VALUES
( 1) , (2), (3), (4), (5);
-- EXCEPT filters for DISTINCT values
SELECT * FROM #NewCustomers AS nc
EXCEPT
SELECT * FROM #ExistingCustomers AS ec
-- NOT IN returns all values without filtering
SELECT * FROM #NewCustomers AS nc
WHERE ID NOT IN (SELECT ID FROM #ExistingCustomers AS ec)
从以上两个查询中,EXCEPT
返回的3行#NewCustomers
,过滤出匹配的1和3,#ExistingCustomers
以及重复的8。
NOT IN
不执行这种独特的过滤,并从#NewCustomers
重复的8 返回4行。
如果我们现在在添加NULL
到#ExistingCustomers
表格中,我们看到返回的结果相同EXCEPT
,但NOT IN
将返回一个空的结果集。
INSERT INTO #ExistingCustomers
( ID )
VALUES
( NULL );
-- With NULL values in the right-hand table, EXCEPT still returns the same results as above
SELECT * FROM #NewCustomers AS nc
EXCEPT
SELECT * FROM #ExistingCustomers AS ec
-- NOT IN now returns no results
SELECT * FROM #NewCustomers AS nc
WHERE ID NOT IN (SELECT ID FROM #ExistingCustomers AS ec)
DROP TABLE #NewCustomers;
DROP TABLE #ExistingCustomers;
相反NOT IN
,您应该真正看一下,NOT EXISTS
并且在Gail Shaw的博客上可以很好地比较两者。
Mark Sinkinson的出色评论的补充:
NOT IN要求您将一个表中的单个列与另一表或子查询中的单个列进行比较。
实际上,您可以执行NOT IN
不止一列。
例如,这是完全合法的* SQL查询:
SELECT E.first_name, E.last_name
FROM employees E
WHERE (E.first_name, E.last_name) NOT IN
(SELECT M.first_name, M.last_name FROM managers M)
这将返回,first_name
并且last_name
是所有员工,但同时也不是经理。
*:但是该构造尚未在SQL Server中实现。