根据ID的范围从层次结构中进行选择

时间:2015-02-03 09:05:16

标签: sql sql-server tsql tree hierarchy

我有一个持有分层结构的表,所以基本上它有3列:

enter image description here

我想要的是从这个表中选择一系列ID,例如:

Id IN (1,4,8,18)   

导致:

enter image description here

  

换句话说,一行必须与所有父母和孩子一起进入结果集。

我怎么能解决这个问题呢? 提前致谢

3 个答案:

答案 0 :(得分:1)

您可以使用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,用于获取父母和孩子。最后,你将这两个结果结合起来以获得不同的行。

我有一个小虫子。编辑...

答案 1 :(得分:1)

将您的任务分成两个步骤

  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
    

答案 2 :(得分:0)

您可以使用递归公用表表达式(CTE)。这种任务非常好。下面我假设tbl是你的表名。

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;

如果您发现某些记录多次返回。