找到所有非父母的孩子

时间:2012-09-26 13:01:50

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

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

表格如下所示

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)

但这会返回所有行

任何人都可以告诉我我缺少的东西

谢谢!

6 个答案:

答案 0 :(得分:7)

使用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 <> 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)

答案 1 :(得分:3)

您可以使用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的行。因此,这不是父母。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

  

为什么它不起作用。

您正在检索第一个查询中没有行:

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

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

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

与sQL NOT EXISTS中的所有其他谓词不同,两个值逻辑TRUEFALSE的工作原理是,只有两个值存在(ture)或false的可能性存在无法返回UNKNOWN

还有另一种解决方法,在您的情况下无法获得您想要的内容,即使用NULL消除这些AND ParentID IS NOT NULL值,但在您的情况下不会得到您您正在寻找的结果

答案 4 :(得分:0)

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

SELECT ID
FROM [SMD].[dbo].[ProposalFollowUp]

EXCEPT

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

答案 5 :(得分:0)

Relace = on&lt;&gt;

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)