SQL Server 结果不同:NOT IN 与 LEFT JOIN with IS NULL

问题描述 投票:0回答:2

今天遇到了一个不太明白的问题,所以希望能得到一些外部知识。我试图找到一个表中的项目数,其中它们的 id 未在另一个表中引用。我运行了两个不同的查询,结果似乎相互矛盾。

select count(*)
from TableA
where ID not in (select aID from TableB)

返回0

select count(*)
from TableA a
left join TableB b on b.aID = a.ID
where b.aID is null

返回几千。

TableA和TableB中的所有ID都是唯一的。表 A 中的 ID 绝不会多次出现在表 B 的 aID 列中。对我来说,似乎我在查询同一件事,但收到不同的结果。我哪里错了?

sql sql-server left-join notin
2个回答
2
投票

请勿将

not in
与子查询一起使用。如果子查询中的任何值为NULL
,则过滤掉
所有行。这些是 SQL 中定义 NULL
 的规则。 
LEFT JOIN
 是正确的。

原因是

NULL

表示未知值。几乎任何与 
NULL
 的比较都会返回 
NULL
,这被视为 false。因此, 
NOT IN
NULL
 的唯一可能性是某个元素与您要查找的内容匹配 - 并且表达式返回 
false
 - 或者一个元素是 
NULL
 - 并且表达式返回 
NULL
被视为 
false

我通常建议将

NOT IN

 替换为 
NOT EXISTS
:

select count(*) from TableA a where not exists (select 1 from TableB b where b.aID = a.ID);

LEFT JOIN

 运行正确并且通常具有良好的性能。


0
投票
如果涉及的列可以为空,我们应该始终使用 EXISTS 运算符。而且,Exist 比 In 子句更快。

使用 IN/Not IN 运算符可能会产生较差的计划,并且如果像您的情况一样在表中插入空值,也可能导致误导结果。

© www.soinside.com 2019 - 2024. All rights reserved.