Ian*_*oyd 7 sql-server null celko
为什么进行比较value
,以null
返回false,使用时除外NOT IN
,它返回true?
给定查询以查找具有帖子的所有stackoverflow用户:
SELECT * FROM Users
WHERE UserID IN (SELECT UserID FROM Posts)
Run Code Online (Sandbox Code Playgroud)
这按预期工作; 我得到一个有帖子的所有用户的列表.
现在查询逆; 找到所有没有帖子的stackoverflow用户:
SELECT * FROM Users
WHERE UserID NOT IN (SELECT UserID FROM Posts)
Run Code Online (Sandbox Code Playgroud)
这不返回任何记录,这是不正确的.
给出假设数据1
Users Posts
================ ===============================
UserID Username PostID UserID Subject
------ -------- ------- ------ ----------------
1 atkins 1 1 Welcome to stack ov...
2 joels 2 2 Welcome all!
... ... ... ...
399573 gt6989b ... ...
... ... ... ...
10592 null (deleted by nsl&fbi...
... ...
Run Code Online (Sandbox Code Playgroud)
并假设NULL规则:
NULL = NULL
评估为未知NULL <> NULL
评估为未知value = NULL
评估未知如果我们看一下第二个查询,我们感兴趣的是找出其中Users.UserID的所有行未在列Posts.UserID发现.我将按逻辑进行如下操作:
检查UserID 1
1 = 1
返回true.因此,我们得出结论,该用户有一些帖子,并且不将它们包含在输出列表中现在检查UserID 2:
2 = 1
返回false,所以我们继续寻找2 = 2
返回true,因此我们得出结论,该用户有一些帖子,并且不将它们包含在输出列表中现在检查UserID 399573
399573 = 1
返回false,所以我们继续寻找399573 = 2
返回false,所以我们继续寻找399573 = null
回报未知,所以我们继续寻找我们没有找到UserID 399573的帖子,因此我们将其包含在输出列表中.
除了SQL Server不这样做.如果你的中有NULLin
列表中,则突然发现匹配.它突然找到一个匹配.突然399573 = null
评估为真.
为什么比较 value
来null
还不得而知,当它返回true除?
编辑:我知道我可以通过专门排除空值来解决这种荒谬的行为:
SELECT * FROM Users
WHERE UserID NOT IN (
SELECT UserID FROM Posts
WHERE UserID IS NOT NULL)
Run Code Online (Sandbox Code Playgroud)
但我不应该,至于我可以告诉布尔逻辑没有它应该没问题 - 因此我的问题.
A-K*_*A-K 10
常见问题,罐头答案:
NOT IN子句的行为可能会令人困惑,因此需要一些解释.请考虑以下查询:
SELECT LastName, FirstName FROM Person.Contact WHERE LastName NOT IN('Hedlund', 'Holloway', NULL)
Run Code Online (Sandbox Code Playgroud)
虽然AdventureWorks.Person.Contact中有超过一千个不同的姓氏,但查询不返回任何内容.这可能与初学者数据库程序员看起来有悖常理,但它实际上非常有意义.解释包括几个简单的步骤.首先,考虑以下两个查询,它们明显相同:
SELECT LastName, FirstName FROM Person.Contact
WHERE LastName IN('Hedlund', 'Holloway', NULL)
SELECT LastName, FirstName FROM Person.Contact
WHERE LastName='Hedlund' OR LastName='Holloway' OR LastName=NULL
Run Code Online (Sandbox Code Playgroud)
请注意,两个查询都返回预期结果.现在,让我们回顾一下DeMorgan的定理,该定理指出:
not (P and Q) = (not P) or (not Q)
not (P or Q) = (not P) and (not Q)
Run Code Online (Sandbox Code Playgroud)
我正在从维基百科(http://en.wikipedia.org/wiki/De_Morgan_duality)剪辑和粘贴.将DeMorgan定理应用于此查询,因此这两个查询也是等价的:
SELECT LastName, FirstName FROM Person.Contact WHERE LastName NOT IN('Hedlund', 'Holloway', NULL)
SELECT LastName, FirstName FROM Person.Contact
WHERE LastName<>'Hedlund' AND LastName<>'Holloway' AND LastName<>NULL
Run Code Online (Sandbox Code Playgroud)
最后一个LastName <> NULL永远不会成立
你的第一句话中的假设是不正确的:
为什么value与null的比较返回false,除非使用NOT IN,它返回true?
但是将值与null进行比较不会返回false
; 它返回unknown
.并unknown
有自己的逻辑:
unknown AND true = unknown
unknown OR true = true
unknown OR false = unknown
Run Code Online (Sandbox Code Playgroud)
这是如何解决的一个例子:
where 1 not in (2, null)
--> where 1 <> 2 and 1 <> null
--> where true and unknown
--> where unknown
Run Code Online (Sandbox Code Playgroud)
该where
子句仅匹配true
,因此这将过滤掉任何行.
你可以在维基百科上找到3值逻辑的全部荣耀.
归档时间: |
|
查看次数: |
12074 次 |
最近记录: |