Answers:
EXCEPT和之间有两个主要区别NOT IN。
EXCEPT过滤DISTINCT左侧表中未出现在右侧表中的值。本质上与NOT EXISTSwith 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中实现。