今天遇到了一个不太明白的问题,所以希望能得到一些外部知识。我试图找到一个表中的项目数,其中它们的 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 列中。对我来说,似乎我在查询同一件事,但收到不同的结果。我哪里错了?
请勿将
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
运行正确并且通常具有良好的性能。
使用 IN/Not IN 运算符可能会产生较差的计划,并且如果像您的情况一样在表中插入空值,也可能导致误导结果。