Select 来自基于 ID 范围的层次结构

Select from a hierarchy based on a range of ID's

我 table 持有一个层次结构,所以基本上它有 3 列:

我想要的是 select 从这个 table 通过一系列 ID,例如:

Id IN (1,4,8,18)   

结果为:

In other word a row must come into result set with all of it's parents and children.

我该如何解决这个问题?
提前致谢

您可以使用递归通用 table 表达式 (CTE)。它非常擅长这类任务。下面我假设 tbl 是您的 table 的名称。

WITH UserCTE AS
(

SELECT Id, name, ParentId
FROM tbl
WHERE Id in (1,4,8,18)

UNION ALL

SELECT P.Id, P.name, P.ParentId
FROM UserCTE AS C --- C for child
JOIN tbl AS P --- P for parent
ON C.ParentId = P.Id

)
SELECT Id, name, ParentId
FROM UserCTE;

您也可以尝试使用

SELECT DISTINCT Id, name, ParentId
FROM UserCTE;

如果您注意到某些记录被多次返回。

您可以使用 CTE 来完成:

DECLARE @t TABLE ( ID INT, ParentID INT )

INSERT  INTO @t
VALUES  ( 1, NULL ),
        ( 2, 1 ),
        ( 3, 2 ),
        ( 4, 3 ),
        ( 6, NULL ),
        ( 7, 6 ),
        ( 8, 7 ),
        ( 9, 8 ),
        ( 10, 9 ),
        ( 11, 10 ),
        ( 13, NULL ),
        ( 14, 13 ),
        ( 15, 14 ),
        ( 17, NULL ),
        ( 18, 17 ),
        ( 19, 18 ),
        ( 20, 19 );

WITH    ctep
          AS ( SELECT   *
               FROM     @t
               WHERE    ID IN ( 1, 4, 8, 18 )
               UNION ALL
               SELECT   t.*
               FROM     @t t
                        JOIN ctep ON t.ParentID = ctep.ID
             ),
        ctec
          AS ( SELECT   *
               FROM     @t
               WHERE    ID IN ( 1, 4, 8, 18 )
               UNION ALL
               SELECT   t.*
               FROM     @t t
                        JOIN ctec ON t.ID = ctec.ParentID
             )
    SELECT  * FROM    ctep
    UNION
    SELECT  * FROM    ctec

这里有 2 个 CTE,用于获得 parents 和孩子。最后,您合并这 2 个结果以获得不同的行。

我有一个小错误。已编辑...

将您的任务分成两个步骤

  1. 找到最顶层的父级
  2. 找到所有死者

    WITH ToTopParent AS
    (
        SELECT Id, ParentId
        FROM yourTable
        WHERE Id IN (1,4,8,18) 
    
        UNION ALL
    
        SELECT T.Id, T.ParentId
        FROM ToTopParent TTP
        JOIN yourTable T ON TTP.ParentId = T.Id
    ),
    AllDecedents AS
    (
        SELECT Id, Name, ParentID
        FROM yourTable 
        WHERE id IN (SELECT Id FROM ToTopParent WHERE ParentId IS NULL)
    
        UNION ALL
    
        SELECT T.Id, T.Name, T.ParentID
        FROM yourTable T
        JOIN AllDecedents ON T.ParentId = AllDecedents.Id
    )
    SELECT * FROM AllDecedents