SQL不参加vs左联接

时间:2020-05-15 21:47:44

标签: sql sql-server

我今天遇到了一个我不太了解的问题,所以我希望获得一些外部知识。我试图在一个表中查找没有在另一个表中引用其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都是唯一的。来自TableA的ID不会多次出现在来自TableB的aID列中。对我来说,似乎我在查询同一件事,但收到不同的结果。我要去哪里错了?

2 个答案:

答案 0 :(得分:2)

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

原因是NULL表示未知值。几乎所有与NULL的比较都会返回NULL,这被视为false。因此,将NOT INNULL一起使用的唯一可能性是,一个元素与您要查找的内容相匹配-表达式返回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的性能正常,并且通常具有良好的性能。

答案 1 :(得分:0)

如果涉及的列为可为空,则应始终使用EXISTS运算符。另外,Exist比In子句快。

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