我尝试从一个表中选择一些物质数据,并具有一个限制,即该材料不应存在于一个视图中。
所以,下面是我的代码。它不能正常执行。
select *
from Table A
where Table A.Material not in (select View A.material from View A)
此查询总是执行并直到随着时间的流逝。但是,如果我使用限制,则可以正常执行。
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)
)
这很奇怪,所以我的原始代码的问题在哪里?
您可能在 ViewA.material
中有一些null-s。解决您的问题的另一种方法是:
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
,因此此查询永远不会返回任何结果。
这是一个不存在的问题,它确实会引起一些问题:这是第一个链接:https://explainextendended.com/2009/09/15/not-inot-inot-inot-not-exists-vs-vs-left-join-is-is-null-sql-sql-server/
这是此主题的另一个讨论:https://dba.stackexchange.com/questions/121034/best-practice-between-usis-using-left-join-oin-or-not-exists
可能是因为您使用的是视图,而不是表。该表可能有索引,而视图没有,这就是您因引擎而失去优化的地方。如果您尝试查看计划,您可能会很快看到正在发生的事情