一尘不染

NOT IN(子查询)产生零行

sql

我不断寻找利用配方的过程的例子

WHERE a NOT IN (SELECT b FROM x)

只返回零行,这似乎是错误的。如果我将NOT
IN更改为IN,则它不会返回相反的值(所有行),实际上,它会忽略a不为null的所有行。这已经开始发生在通宵运行的例程中,这些例程运行了好几年并且没有更改。感觉像SQL
Server中有一个错误。

我可以通过改写为

LEFT JOIN x on a = b
WHERE b IS NULL

但这不是我想要忍受的东西。

可能与统计有关吗?一个已知的错误?在最近的示例中,子查询中的表位于远程链接服务器上,尽管我不确定每次看到这种情况都是如此。


阅读 126

收藏
2021-05-23

共1个答案

一尘不染

如果可以b为空,则这不是错误。问题是SQL Server变成NOT IN了一系列<> 1 AND <> 2 AND <> 3等。如果有<> NULL,则返回unknown,在这种情况下表示false。在不同的情况下,这可能会限制或取消 所有 行的资格。而不是LEFT JOIN方法,你应该说:

FROM dbo.OuterTable AS t
WHERE NOT EXISTS (SELECT 1 FROM x WHERE b = t.a);

这是一个快速演示:

DECLARE @x TABLE(i INT);
INSERT @x VALUES(1),(2);

DECLARE @y TABLE(j INT);
INSERT @y VALUES(2),(NULL);

SELECT i FROM @x WHERE i NOT IN -- produces zero results
  (SELECT j FROM @y);

SELECT i FROM @x  AS x WHERE NOT EXISTS -- produces one result
  (SELECT 1 FROM @y WHERE j = x.i);

有关更多详细信息(以及可以证明为什么NOT EXISTS是最佳选择的度量标准):

http://www.sqlperformance.com/2012/12/t-sql-queries/left-anti-semi-
join

另外,请阅读Gail Shaw的这篇博客文章:

http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-
in/

2021-05-23