从父子层次结构表中获取顶级父ID

时间:2015-12-08 19:43:36

标签: sql sql-server

我有层次结构表。如果用户查询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层次结构节点。

1 个答案:

答案 0 :(得分:0)

我不清楚你的意思是什么,为什么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将该列表定义为自己的表格并将第一个查询加入其中。