找到所有非父母的孩子

Mar*_*arc 4 sql sql-server sql-server-2012

我正在试图找回所有不是父母的孩子.

该表看起来像这样

ID  |  ParentID
---------------
1        NULL
2         1
3        NULL
4         2
Run Code Online (Sandbox Code Playgroud)

起初我试过了

SELECT *
FROM [SMD].[dbo].[ProposalFollowUp]
WHERE ID NOT IN (SELECT ParentID FROM [SMD].[dbo].[ProposalFollowUp])
Run Code Online (Sandbox Code Playgroud)

但它不返回任何行.我想选择不在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)
Run Code Online (Sandbox Code Playgroud)

但这会返回所有行

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

谢谢!

And*_*mar 7

使用not in公开一个众所周知的SQL怪癖:

WHERE ID NOT IN (SELECT ParentID FROM [SMD].[dbo].[ProposalFollowUp])
Run Code Online (Sandbox Code Playgroud)

要了解原因,请查询以下内容:

WHERE ID NOT IN (null, 1, null, 2)
Run Code Online (Sandbox Code Playgroud)

这转化为:

where id <> null and id <> 1 and id <> null and id <> 2
Run Code Online (Sandbox Code Playgroud)

诀窍是id <> null永远不会是真的.在SQL的三值逻辑中,它的计算结果为unknown.这意味着你的where子句永远不会批准任何行.

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

WHERE ID NOT IN (
    SELECT ParentID FROM [SMD].[dbo].[ProposalFollowUp] WHERE ParentID IS NOT NULL)
Run Code Online (Sandbox Code Playgroud)