Rbj*_*bjz 5 sql null left-join in-subquery
我遇到了这个有趣的行为.我看到左连接是要走的路,但仍然希望将其清除.是设计中的错误还是行为?有什么解释吗?
当我从左表中选择记录时,右表上子查询的结果中不存在值,如果子查询结果为空,则不返回预期的"缺失"记录.我期望将此查询编写为等效的两种方法.
谢谢!
declare @left table (id int not null primary key identity(1,1), ref int null)
declare @right table (id int not null primary key identity(1,1), ref int null)
insert @left (ref) values (1)
insert @left (ref) values (2)
insert @right (ref) values (1)
insert @right (ref) values (null)
print 'unexpected empty resultset:'
select * from @left
where ref not in (select ref from @right)
print 'expected result - ref 2:'
select * from @left
where ref not in (select ref from @right where ref is not null)
print 'expected result - ref 2:'
select l.* from @left l
left join @right r on r.ref = l.ref
where r.id is null
print @@version
Run Code Online (Sandbox Code Playgroud)
得到:
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
unexpected empty resultset:
id ref
----------- -----------
(0 row(s) affected)
expected result - ref 2:
id ref
----------- -----------
2 2
(1 row(s) affected)
expected result - ref 2:
id ref
----------- -----------
2 2
(1 row(s) affected)
Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64)
Apr 2 2010 15:48:46
Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows NT 6.0 <X64> (Build 6002: Service Pack 2) (Hypervisor)
Run Code Online (Sandbox Code Playgroud)
这是设计的.如果匹配失败并且set包含NULL,则结果为NULL,如SQL标准所指定.
'1' IN ('1', '3') => true
'2' IN ('1', '3') => false
'1' IN ('1', NULL) => true
'2' IN ('1', NULL) => NULL
'1' NOT IN ('1', '3') => false
'2' NOT IN ('1', '3') => true
'1' NOT IN ('1', NULL) => false
'2' NOT IN ('1', NULL) => NULL
非正式地,这背后的逻辑是NULL可以被认为是未知值.例如,这里未知值是什么并不重要 - "1"显然在集合中,因此结果为真.
'1' IN ('1', NULL) => true
Run Code Online (Sandbox Code Playgroud)
在下面的示例中,我们无法确定集合中是否存在"2",但由于我们不知道所有值,因此我们也无法确定它是否在集合中.所以结果是NULL.
'2' IN ('1', NULL) => NULL
Run Code Online (Sandbox Code Playgroud)
另一种看待它的方法是重写x NOT IN (Y, Z)为X <> Y AND X <> Z.然后你可以使用三值逻辑的规则:
true AND NULL => NULL
false AND NULL => false
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2720 次 |
| 最近记录: |