我一直在寻找使用该配方的流程的例子
WHERE a NOT IN (SELECT b FROM x)
只是返回零行似乎错了。如果我将NOT IN更改为IN,则它不会返回inverse(所有行),实际上它会遗漏a中非null的所有行。 这种情况已经开始发生在过夜的例程中,这些例程已经运行多年并且没有改变。感觉SQL Server中存在一个错误。
我可以通过重新制定来解决问题
LEFT JOIN x on a = b
WHERE b IS NULL
但这不是我想要忍受的东西。
这可能与统计数据有关吗?一个已知的bug?在最近的示例中,子查询中的表位于远程链接服务器上,但我不确定每次看到它时都会出现这种情况。
答案 0 :(得分:11)
如果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/
答案 1 :(得分:0)
Aaron很好地解释了这种行为的根本原因。它可以通过多种方式解决, - LEFT JOIN,通过从where子句或select子句中过滤掉来自内部查询的NULL值,使用共同相关的子查询 - 仅举几例。
以下帖子是同一主题案例研究的一部分: - NOT IN Subquery return zero rows -Workarounds