【问题标题】:CTE to return all items in hierarchyCTE 返回层次结构中的所有项目
【发布时间】:2012-09-28 14:28:45
【问题描述】:

我有一个具有递归层次结构的表(即 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,但我无法正确解决!任何帮助表示赞赏。

【问题讨论】:

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


【解决方案1】:
;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

【讨论】:

  • 非常好,完美运行。只是为了厚脸皮......你能想出一种方法来稍微优化一下,通过在最后消除对嵌套选择的需要吗?
  • 取决于您是否希望它们按顺序排列?
  • 我正在使用此查询的结果来返回更多信息,因此我最终将按日期顺序返回数据(以及相关数据)。所以简单地说,不,我只需要ID和Level。
  • 你可以这样做 select distinct id, parent, 1+ level- (select MIN(level) from cte2) as Level from cte2 (实际上,你可以按级别订购)
【解决方案2】:

我能想到的最简单的 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

【讨论】:

  • 我将此查询放入视图中,但不确定这是否是最佳做法。
【解决方案3】:
;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); 

【讨论】:

    猜你喜欢
    • 2015-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多