4

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

桌子看起来像这样

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)

但这会返回所有行

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

谢谢!

4

6 回答 6

7

Usingnot 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 的三值逻辑中,它的计算结果为unknown。这意味着您的 where 子句永远不会批准任何行。

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

WHERE ID NOT IN (
    SELECT ParentID FROM [SMD].[dbo].[ProposalFollowUp] WHERE ParentID IS NOT NULL)
于 2012-09-26T13:07:11.960 回答
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另一行中的行。因此,这不是父母。

于 2012-09-26T13:05:30.107 回答
1
SELECT *
FROM [SMD].[dbo].[ProposalFollowUp]
WHERE ID NOT IN (SELECT ParentID FROM [SMD].[dbo].[ProposalFollowUp] WHERE ParentID  IS NOT NULL)
于 2012-09-26T13:04:08.767 回答
1

为什么它不起作用。

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

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

由于谓词的NULL值变得因此不返回任何内容,您可以通过使用来避免这种情况:ParentIDUNKNOWNNOT EXISTS

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

与 SQL 中的所有其他谓词不同,它NOT EXISTS适用于两个值逻辑TRUE,并且FALSE因为该值只有两个概率存在(ture)或 false,所以无法返回UNKNOWN

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

于 2012-09-26T13:08:01.373 回答
0

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

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

EXCEPT

SELECT ParentID
FROM [SMD].[dbo].[ProposalFollowUp] ;
于 2012-09-26T13:16:49.687 回答
0

替换 = 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)
于 2012-09-26T13:21:17.750 回答