为什么按限制选择查询Not IN不能正常执行,但是按Restriction IN可以正常执行?

时间:2019-06-26 03:05:44

标签: sql sql-server

我尝试从一个表中选择一些物料数据,并且有一个限制,即该物料不应存在于一个视图中。

所以,下面是我的代码。无法正常执行。

select *
from Table A
where Table A.Material not in (select View A.material from View A)

此查询始终执行并一直执行。 但是,如果我使用Restriction IN,它可以正常执行。

select *
from Table A
where Table A.Material in (select View A.material from View A)

要获取目标数据,我使用下面的代码,它可以正常工作。

select *
from Table A
where Table A.Material not in (select *
                               from Table A 
                               where Table A.Material in (select View A.material from View A)
                              )

这很奇怪,我的原始代码在哪里出现?

2 个答案:

答案 0 :(得分:1)

您可能在ViewA.material中有一些NULL。解决问题的另一种方法是:

select * from TableA where TableA.Material not in (select ViewA.material from ViewA where ViewA.material IS NOT NULL)

让我们假设ViewA.material的值为1、2和NULL。使用IN进行的查询等同于:

select * from TableA where Material=1 OR Material=2 OR Material=NULL

即使TableA包含具有NULL的行,条件Material=NULL也不会为真,因为NULL = NULL是未知的(至少在默认和建议的设置SET ANSI_NULLS ON下)。但是TRUE OR unknown会产生TRUE,因此此查询会产生正确的结果。

使用NOT IN进行的查询等同于:

select * from TableA where Material<>1 AND Material<>2 AND Material<>NULL

在这种情况下,TRUE AND unknown会产生unknown,因此此查询将永远不会返回任何结果。

答案 1 :(得分:0)

这是NOT IN的问题,它确实引起一些问题: 这是第一个链接:https://explainextended.com/2009/09/15/not-in-vs-not-exists-vs-left-join-is-null-sql-server/
这是该主题的另一讨论:https://dba.stackexchange.com/questions/121034/best-practice-between-using-left-join-or-not-exists

可能是因为您使用的是VIEW,而不是TABLE。 TABLE可能有索引,而VIEW没有索引,这就是引擎失去优化的地方。如果您尝试查看plan,则可能很快就会看到发生了什么事