【问题标题】:Get the top level parent id from a parent-child hierarchy table从父子层次表中获取顶级父 id
【发布时间】:2016-03-13 21:21:22
【问题描述】:

我有层次结构表。如果用户查询 id 列表,则输出应该只是层次结构中任何提供的值的顶级 id。如果父 ID 在列表中可用,则应返回它,否则应返回子 ID。

下表是一个例子:

id   parentid
-------------
1  |  null
2  |  1
3  |  1
4  |  2
5  |  4
6  |  3

如果我查询 2,4,5,6 我需要得到输出 2,6

输出不应返回 4(因为父级 2 已经在列表中)并且不应返回 5,因为顶级层次结构父级 (5-->4-->2) 也在提供的列表中可用。

即,如果提供的列表包含来自同一层次结构的值,则应为输出中的特定层次结构返回 TOP 层次结构节点。

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    我不完全清楚你为什么不将 5 包含在输出中的意思,但这会给你结果:

    select id from mytable where id in (2,4,5,6) and parentid not in (2,4,5,6)
    

    要在排除值方面再上一层,您必须将表连接到自身。像这样的:

    select id from mytable join mytable parenttab on mytable.parentid = parenttab.id
     where mytable.id in (2,4,5,6) and
           mytable.parentid not in (2,4,5,6) and
           parenttab.parentid not in (2,4,5,6)
    

    如果您想进入任何层次结构,您需要使用recursive CTE。像这样的:

    WITH RecursiveParentList ( parentid )
    AS
    (
        SELECT parentid from Mytable 
        where id in (2,4,5,6)
    
        UNION ALL
    
        SELECT ParentTable.id
          FROM Mytable AS ParentTable
          INNER JOIN RecursiveParentList AS ChildTable
                     ON ParentTable.id = ChildTable.parentid
    )
    SELECT MyTable.id
      FROM MyTable
           LEFT JOIN RecursiveParentList on MyTable.id = RecursiveParentList.id
     WHERE RecursiveParentList.id is null;
    

    注意 1:您需要对此进行调试。我把它从我的头顶上拉下来,不会测试它。

    注意 2:我只会将 IN 子句用于像这样的简短列表。如果您的排除项目列表变长或从另一个表中提取,您将需要使用另一个 CTE 将该列表定义为它自己的表并将您的第一个查询加入到它。

    【讨论】:

    • 5 是 2 (2 --> 4 --> 5) 的层次结构子级,因为 2 在输出中 5 不应该在那里
    • 好吧,我给你的 sql 会给你你想要的结果,但只是因为 5 在层次结构 4 --> 5 中,并且由于 4 在列表中,所以它的父级被省略了。所以这只会在层次结构中上升一级。如果您希望能够更深入,则必须将表连接到自身。你想深入多少?两级就够了吗?
    • 它应该是任何层级
    • 好的,你可以使用递归 CTE,我将其添加到我的答案中
    • 不确定该查询,因为5从未根据上述查询被过滤,请您帮助理解。
    猜你喜欢
    • 2023-03-31
    • 1970-01-01
    • 2015-07-28
    • 1970-01-01
    • 1970-01-01
    • 2021-07-05
    • 2020-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多