NOT IN子句和NULL值
当我获得了不同的记录计数时,就出现了这个问题,我认为这是相同的查询,一个使用" not in" where约束,另一个使用左联接。处于"非限制"约束的表具有一个空值(错误数据),这导致该查询返回0条记录的计数。我有点理解为什么,但是我可以使用一些帮助来完全理解这个概念。
简单地说,为什么查询A返回结果而B不返回结果?
A: select 'true' where 3 in (1, 2, 3, null) B: select 'true' where 3 not in (1, 2, null)
这是在SQL Server 2005上。我还发现调用set ansi_nulls off
会导致B返回结果。
解决方案
除非我们使用IS NULL,否则比较为null是未定义的。
因此,将3与NULL进行比较(查询A)时,它将返回undefined。
IE。 SELECT'true'其中3 in(1,2,null)
和
SELECT'true'其中3不在(1,2,null)中
将产生相同的结果,因为NOT(UNDEFINED)仍未定义,但不是TRUE
在A中,针对集合中的每个成员测试3个是否相等,得出(FALSE,FALSE,TRUE,UNKNOWN)。由于元素之一为TRUE,因此条件为TRUE。 (也有可能在此处发生一些短路,因此,一旦它碰到第一个TRUE,它实际上就会停止,并且永远不会求值3 = NULL。
在B中,我认为它将条件评估为NOT((1,2,null)中的3)。针对设定的收益率(FALSE,FALSE,UNKNOWN)测试3的相等性,该收益率汇总为UNKNOWN。 NOT(UNKNOWN)产生UNKNOWN。因此,总体而言,该条件的真相是未知的,最后将其本质上视为FALSE。
与未知值比较时," NOT IN"将返回0条记录
由于未知的是NULL,因此在可能值列表中包含NULL或者NULL的NOT IN查询将始终返回0记录,因为无法确定NULL。值不是要测试的值。
查询A与以下内容相同:
select 'true' where 3 = 1 or 3 = 2 or 3 = 3 or 3 = null
由于" 3 = 3"为真,因此可以得到结果。
查询B与以下内容相同:
select 'true' where 3 <> 1 and 3 <> 2 and 3 <> null
当ansi_nulls
启用时,3 <> null
为UNKNOWN,因此该谓词的值为UNKNOWN,并且我们不会得到任何行。
当ansi_nulls
关闭时,3 <> null
为true,因此谓词的值为true,我们将获得一行。
Null表示缺少数据,即未知,不是没有数据值的数据。对于具有编程背景的人们来说,这很容易造成混淆,因为在C类型语言中使用指针时,null确实不算什么。
因此,在第一种情况下3确实在(1,2,3,null)的集合中,因此返回true
但是在第二个中,我们可以将其减少到
选择" true",其中3个不为(空)
因此,不会返回任何内容,因为解析器对与之比较的集合一无所知,它不是一个空集合,而是一个未知集合。使用(1,2,null)并没有帮助,因为(1,2)设置显然是假的,但是接下来我们要针对未知的对象(未知)进行操作。
这也可能有助于了解join,exist和in之间的逻辑差异
http://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210.aspx
每当我们使用NULL时,我们实际上是在处理三值逻辑。
当WHERE子句求值时,第一个查询将返回结果:
3 = 1 or 3 = 2 or 3 = 3 or 3 = null which is: FALSE or FALSE or TRUE or UNKNOWN which evaluates to TRUE
第二个:
3 <> 1 and 3 <> 2 and 3 <> null which evaluates to: TRUE and TRUE and UNKNOWN which evaluates to: UNKNOWN
UNKNOWN与FALSE不同
我们可以通过调用以下命令轻松对其进行测试:
select 'true' where 3 <> null select 'true' where not (3 <> null)
这两个查询都不会给我们任何结果
如果UNKNOWN与FALSE相同,则假定第一个查询为FALSE,则第二个查询将求值为TRUE,因为它与NOT(FALSE)相同。
事实并非如此。
在SqlServerCentral上有关于此主题的非常好的文章。
整个NULL和三值逻辑问题一开始可能会让人有些困惑,但是必须理解才能在TSQL中编写正确的查询,这是必不可少的
我推荐的另一篇文章是SQL Aggregate Functions和NULL。
这是给男孩的:
select party_code from abc as a where party_code not in (select party_code from xyz where party_code = a.party_code);
不管ansi设置如何