SELECT FROM WHERE X NOT IN Y的意外结果

时间:2018-02-13 07:42:38

标签: sql sql-server azure-sql-database sql-server-2016

因此...

select COUNT(*) cnt from docDocument d 
inner join tblAttachment a on d.AttachmentID = a.ID
where
a.ContainerID = 1 

返回6673

select COUNT(*) from tblAttachment 
where 
ContainerID = 1 

返回10372

select COUNT(*) cnt from docDocument d 
right join tblAttachment a on d.AttachmentID = a.ID
where
a.ContainerID = 1 
AND
d.ID IS NULL

返回3699,这有意义,因为10372 - 6673 = 3699

SELECT COUNT(*) FROM
(
select ID from tblAttachment a
where 
a.ContainerID = 1
Except
(
    SELECT AttachmentId from docDocument 
)
) tst

不出所料地返回3699 ......但是......

select COUNT(*) from tblAttachment a
where 
a.ContainerID = 1 AND
a.ID NOT IN
(
    SELECT d.AttachmentId from docDocument  d
)

我原本期待这回到3699,但令人惊讶的是它会回归0.

有人可以解释这些结果吗?

3 个答案:

答案 0 :(得分:4)

如果子查询返回空值,则NOT IN不再为真,并且不返回任何行。

要返回的aviod null值:

select COUNT(*) from tblAttachment a
where 
a.ContainerID = 1 AND
a.ID NOT IN
(
    SELECT d.AttachmentId from docDocument  d WHERE d.AttachmentId IS NOT NULL
)

或切换到“null safe”NOT EXISTS

select COUNT(*) from tblAttachment a
where 
a.ContainerID = 1 AND
NOT EXISTS
(
    SELECT * from docDocument  d WHERE d.AttachmentId =  a.ID
)

答案 1 :(得分:2)

您的查询不返回nulls值。所以它显示零记录。

这是您现在正在获得的以下方案。让我们试着理解并做出改变。

select * 
into #tab1 
from (select 'a' Name union all
      select 'b'union all
      select 'c'union all
      select 'd'union all
      select 'e') AS A

select * 
into #tab2 
from (select 'd' Name union all
      select 'e' union all
      select NULL) AS A

不存在

select Name 
from #tab1  
where not exists (select * 
                  from #tab2 
                  where #tab1.Name = #tab2.Name )

左加入

select t1.Name 
from #tab1 t1
left join #tab2 t2 on t1.Name = t2.Name 
where t2.Name is null

不在

select * 
from #tab1 
where Name not in (select Name from #tab2)

注意:只要查询中的Not返回NULL,外部查询就会返回空白数据。

答案 2 :(得分:1)

您必须在docDocument表中使用NULL值...这就是您没有得到任何内容的原因。

请尝试这样使用不存在

select COUNT(*) from tblAttachment a
where 
a.ContainerID = 1 AND
NOT EXISTS
(
    SELECT d.AttachmentId from docDocument  d
    WHERE a.ID = d.ID
)

您可以使用EXCEPT运算符。

select * into #tab1 from (
select 'a' Name union all
select 'b'union all
select 'c'union all
select 'd'union all
select 'e'

)AS A

select * into #tab2 from 
(
select 'd' Name union all
select 'e' union all
select NULL
)AS A

<强>解

从#tab1中选择姓名
除了 从#tab2中选择*

输出

Name
----
a
b
c

(3 rows affected)