如何查询没有子节点的所有父节点,并且仅在2个级别时查找父节点的现有子节点?

时间:2018-04-17 13:06:02

标签: sql sql-server

英语不是我的第一语言,所以我会尝试尽可能清楚地解释我所寻找的内容。我尝试了很多个小时,但我无法找到我需要的东西。

我有以下表结构,它是一个简单的父/子层次结构。我将只有2个级别(例如:没有孩子的记录,有孩子的记录和那些没有孩子的孩子):

表格结构:

[Id] [int] IDENTITY(1,1) NOT NULL,
[Description] [nvarchar](255) NULL,
[ParentId] [int] NULL,

以下是表格中的数据:

Id          Description       ParentId
----------- ----------------- -----------
1           aaaa              NULL
2           bbbb              NULL
3           cccc              NULL
4           dddd              NULL
5           eeee              NULL
6           ffff              NULL
7           gggg              NULL
8           aaaa-2            1
9           aaaa-3            1
10          bbbb-2            2
11          bbbb-3            2

表格中的数据:

我想查询返回没有孩子的所有记录,以及父母孩子的最后一次出现而没有返回相应的父母。请参阅下一个图像以获得预期结果(我希望查询仅返回以颜色标记的记录):

预期结果:

Id          Description       ParentId
----------- ----------------- -----------
3           cccc              NULL
4           dddd              NULL
5           eeee              NULL
6           ffff              NULL
7           gggg              NULL
9           aaaa-3            1
11          bbbb-3            2

我尝试过类似的事情:

WITH CTE ([Id], [Description], [ParentId], LEVEL) AS
( SELECT [Id], [Description], [ParentId], 1 LEVEL
  FROM [Test].[dbo].[Avis]`enter code here`
  WHERE [ParentId] IS NULL AND [Id] NOT IN ??
  UNION ALL
  SELECT E.[Id], E.[Description], E.[ParentId], CTE.LEVEL + 1
  FROM [Test].[dbo].[Avis] E
      INNER JOIN CTE CTE ON E.[ParentId] = CTE.[Id]
  WHERE E.[ParentId] IS NOT NULL
)
SELECT *
FROM CTE

1 个答案:

答案 0 :(得分:1)

您有两个要求:

  1. 获取不在关系中的所有行
  2. 获取每个父母的最后一个孩子
  3. 基本上,你正试图在每个关系中获得最后一片叶子。

    要获取不在关系中的所有行,请获取那些具有空父ID且其id不用作另一行的父ID的行。

    要获取最后一个子节点,请使用子查询获取每个父ID的最大ID,并使用这些ID选择所需的行。

    您可以将这两个需求拆分为两个带有union的查询,但由于父请求不会对叶子造成伤害,因此您只需将null父ID拆分或使用或者具有max id要求即可。

    SELECT *
    FROM @Avis a
    WHERE a.Id NOT IN (SELECT ParentId FROM @Avis WHERE ParentId IS NOT NULL)
        AND (
            a.ParentId IS NULL 
            OR a.Id IN (SELECT MAX(Id) FROM @Avis WHERE ParentId IS NOT NULL GROUP BY ParentId)
        )
    

    <强>结果

    Id          Description  ParentId
    ----------- ------------ -----------
    3           cccc         NULL
    4           dddd         NULL
    5           eeee         NULL
    6           ffff         NULL
    7           gggg         NULL
    9           aaaa-3       1
    11          bbbb-3       2
    

    奖励:即使关系是多层深度,此查询也会获得每个父级的最后一个叶子。