CTE返回层次结构中的所有项目

时间:2012-09-28 14:28:45

标签: sql-server sql-server-2008 common-table-expression recursive-query

我有一个带有递归层次结构的表(即ID,ParentID)。对于此层次结构中的任何项目,我希望能够返回层次结构的上下两个列表以及每行的级别。假设父母只能拥有一个孩子。

举例如下:

ID    ParentID
--------------
1     NULL
2     1
3     2
4     NULL
5     4
6     5

鉴于ID 1,2或3,我想返回:

ID    ParentID    Level
-----------------------
1     NULL        1
2     1           2
3     2           3

我以前做过这个,但我不记得怎么做了。我知道解决方案涉及CTE,我无法做到正确!任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:5)

;with cte as 
(
    select *, 1 as level from @t where id = @yourid
    union all
    select t.*, level - 1
    from cte 
        inner join @t t on cte.parent = t.id
),
cte2 as
(   
    select * from cte
    union all
    select t.*, level+1
    from cte2 
        inner join @t t on cte2.id = t.parent

)
    select id,parent, ROW_NUMBER() over (order by level) level
    from (  select distinct id, parent, level from cte2) v

答案 1 :(得分:0)

我能提出的最准确的CTE查询版本是:

WITH Ancestry (AncestorID, DescendantID)
AS
(
    SELECT 
        ParentID, ID
    FROM
        dbo.Location
    WHERE
        ParentID IS NOT NULL
UNION ALL
    SELECT 
        P.AncestorID, C.ID
    FROM
        dbo.Location C
    JOIN
        Ancestry P on C.ParentID = P.DescendantID
)
SELECT * FROM Ancestry

结果是表格中存在的所有祖先/后代关系的列表。

最终的“SELECT * FROM Ancestry”可以用更复杂的东西代替,以便过滤,订购等。

要包含自反关系,可以通过在最终的SELECT语句中添加两行来修改查询:

SELECT * FROM Ancestry
UNION
SELECT ID, ID FROM dbo.Location

答案 2 :(得分:-1)

;WITH Recursive_CTE AS (
     SELECT
          child.ExecutiveId,
          CAST(child.ExecutiveName as varchar(100)) BusinessUnit,
          CAST(NULL as bigint) ParentUnitID,
          CAST(NULL as varchar(100)) ParentUnit,
          CAST('' as varchar(100)) LVL,
          CAST(child.ExecutiveId as varchar(100)) Hierarchy,
      1 AS RecursionLevel
     FROM Sales_Executive_level child
     WHERE ExecutiveId = 4000 --your Id which you want to get all parent node
     UNION ALL 
     SELECT
      child.ExecutiveId,
      CAST(LVL + child.ExecutiveName as varchar(100)) AS BusinessUnit,
      child.ParentExecutiveID,
      parent.BusinessUnit ParentUnit,
      CAST('' + LVL as varchar(100)) AS LVL,
      CAST(Hierarchy + ':' + CAST(child.ExecutiveId as varchar(100)) as varchar(100)) Hierarchy,
      RecursionLevel + 1 AS RecursionLevel
     FROM Recursive_CTE parent 
     INNER JOIN Sales_Executive_level child ON child.ParentExecutiveID = parent.ExecutiveId                           
    )
    SELECT * FROM Recursive_CTE ORDER BY Hierarchy  
    OPTION (MAXRECURSION 300);