【问题标题】:Unexpected results from SELECT FROM WHERE X NOT IN YSELECT FROM WHERE X NOT IN Y 的意外结果
【发布时间】:2018-02-13 07:42:37
【问题描述】:

所以...

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。

谁能解释一下这些结果?

【问题讨论】:

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


    【解决方案1】:

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

    要返回的不是 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
    )
    

    【讨论】:

    • 感谢 WHERE d.AttachmentId IS NOT NULL 成功了。我应该想到 NULL 值之前已经咬过我很多次了
    • 你并不孤单。我已经学会了总是不存在。
    【解决方案2】:

    您不在查询中返回空值。所以它显示零记录。

    这是您现在得到的以下场景。让我们试着理解这一点并做出改变。

    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,外部查询就会返回空白数据。

    【讨论】:

      【解决方案3】:

      您必须在 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)
      

      【讨论】:

      • 这也返回 0,原因与上述答案相同
      • 请再次检查。我正在加入不会为 NULL 的 ID 列。您正在加入可以为 NULL 的列,因此您将一无所获。否则,您可以使用 EXCEPT。从 #tab1 中选择名称 除了从 #tab2 中选择 *
      猜你喜欢
      • 2010-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-13
      • 2022-11-12
      • 2019-06-26
      • 2010-10-12
      • 1970-01-01
      相关资源
      最近更新 更多