5

我一直在寻找使用该公式的过程的示例

WHERE a NOT IN (SELECT b FROM x)

只是返回零行,这似乎是错误的。如果我将 NOT IN 更改为 IN,它不会返回相反的(所有行),实际上它会忽略 a 不为空的所有行。这已经开始发生在多年来运行良好并且没有改变的夜间例行程序中。感觉就像 SQL Server 中存在错误。

我可以通过重新制定来解决问题

LEFT JOIN x on a = b
WHERE b IS NULL

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

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

4

2 回答 2

11

如果b可以为空,则这不是错误。问题是 SQL Server 变成NOT IN了一系列<> 1 AND <> 2 AND <> 3等。如果你有<> NULL,那返回未知,在这种情况下意味着 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/

于 2013-10-23T15:03:23.050 回答
0

Aaron 很好地解释了这种行为的根本原因。它可以通过多种方式解决,- LEFT JOIN,通过从 where 子句或 select 子句中过滤掉内部查询中的 NULL 值,使用相关的子查询 - 仅举几例。

以下帖子是关于同一主题的案例研究的一部分:- NOT IN 子查询返回零行-解决方法

于 2014-03-08T15:13:03.220 回答