【问题标题】:Find all children who are not parent查找所有不是父母的孩子
【发布时间】:2012-09-26 13:01:50
【问题描述】:

我正在尝试检索所有不是父母的孩子。

表格是这样的

ID  |  ParentID
---------------
1        NULL
2         1
3        NULL
4         2

一开始我试过

SELECT *
FROM [SMD].[dbo].[ProposalFollowUp]
WHERE ID NOT IN (SELECT ParentID FROM [SMD].[dbo].[ProposalFollowUp])

但它不返回任何行。 我想选择所有不在 parentID 中的行。我不明白为什么它不起作用。

然后我尝试了这个

SELECT *
FROM [SMD].[dbo].[ProposalFollowUp] AS a
WHERE a.ID NOT IN 
(SELECT b.ID FROM [SMD].[dbo].[ProposalFollowUp] as b WHERE b.ParentID = a.ID)

但这会返回所有行

任何人都可以告诉我我错过了什么

谢谢!

【问题讨论】:

    标签: sql sql-server sql-server-2012


    【解决方案1】:

    使用not in 暴露了一个众所周知的 SQL 怪癖:

    WHERE ID NOT IN (SELECT ParentID FROM [SMD].[dbo].[ProposalFollowUp])
    

    要了解原因,请扩展查询:

    WHERE ID NOT IN (null, 1, null, 2)
    

    也就是说:

    where id <> null and id <> 1 and id <> null and id <> 2
    

    诀窍在于id &lt;&gt; null 永远不会是真的。在 SQL 的 three-valued logic 中,它的计算结果为 unknown。这意味着您的 where 子句永远不会批准任何行。

    要解决此问题,请使用 exists(如 Tim Schmelter 的回答),或从子查询中排除 null

    WHERE ID NOT IN (
        SELECT ParentID FROM [SMD].[dbo].[ProposalFollowUp] WHERE ParentID IS NOT NULL)
    

    【讨论】:

      【解决方案2】:

      你可以使用NOT EXISTS:

      SELECT ID, ParentID 
      FROM [SMD].[dbo].[ProposalFollowUp] t1
      WHERE NOT EXISTS
      (
         SELECT 1 FROM [SMD].[dbo].[ProposalFollowUp] t2
         WHERE t2.ParentID = t1.ID
      )
      

      这仅返回 ID 不是另一行中的 ParentID 的行。因此,这不是父母。

      【讨论】:

        【解决方案3】:
        SELECT *
        FROM [SMD].[dbo].[ProposalFollowUp]
        WHERE ID NOT IN (SELECT ParentID FROM [SMD].[dbo].[ProposalFollowUp] WHERE ParentID  IS NOT NULL)
        

        【讨论】:

        • ParentId 用于父级。所以他们可以有父母但没有孩子
        【解决方案4】:

        为什么它不起作用。

        您没有从第一个查询中检索任何行:

        SELECT *
        FROM [SMD].[dbo].[ProposalFollowUp]
        WHERE ID NOT IN (SELECT ParentID FROM [SMD].[dbo].[ProposalFollowUp])
        

        由于ParentID 中的NULL 值,谓词变为UNKNOWN,因此不返回任何内容,您可以使用NOT EXISTS 来避免这种情况:

        SELECT *
        FROM [SMD].[dbo].[ProposalFollowUp]
        WHERE NOT EXISTS (SELECT ParentID FROM [SMD].[dbo].[ProposalFollowUp])
        

        与 SQL 中的所有其他谓词 NOT EXISTS 不同,它适用于两个值逻辑 TRUEFALSE,因为该值只有两个概率存在(ture)或 false 没有办法返回 @987654330 @。

        还有另一种解决方法,在你的情况下不会得到你正在寻找的东西,也就是说,通过使用 AND ParentID IS NOT NULL 消除这些 NULL 值,但在你的情况下不会得到你想要的结果寻找

        【讨论】:

        • WHERE ID NOT EXISTS IN ?不要认为那是 SQL ;)
        • 我猜这是一个错字:WHERE ID NOT EXISTS **IN** (SELECT ...
        • 不幸的是,where id not exists 也不是 SQL。您需要在子查询中使用 where 子句。
        • 别担心,投反对票是为了“无用”的答案,而你的答案是有帮助的!
        【解决方案5】:

        如果你只想要孩子(不是父母)的ID,你也可以使用EXCEPT

        SELECT ID
        FROM [SMD].[dbo].[ProposalFollowUp]
        
        EXCEPT
        
        SELECT ParentID
        FROM [SMD].[dbo].[ProposalFollowUp] ;
        

        【讨论】:

          【解决方案6】:

          Relace = on

          SELECT *
          FROM [SMD].[dbo].[ProposalFollowUp] AS a
          WHERE a.ID NOT IN 
          (SELECT b.ID FROM [SMD].[dbo].[ProposalFollowUp] as b WHERE b.ParentID <> a.ID)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-11-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-05-13
            • 1970-01-01
            相关资源
            最近更新 更多