【问题标题】:Recursive CTE to find all ancestors OF ALL ITEMS递归 CTE 查找所有项目的所有祖先
【发布时间】:2014-06-10 16:16:00
【问题描述】:

我有一个简单的层次结构,需要能够生成一个表,将表中的每个项目与其所有祖先相匹配。 (大写强调这不是一个重复的问题!)

所以这是一张桌子:

Select Item='A', Parent=null into Items union
Select Item='B', Parent='A'  union
Select Item='C', Parent='A'  union
Select Item='D', Parent='B'  union
Select Item='E', Parent='B'  union
Select Item='F', Parent='C'  union
Select Item='G', Parent='C'  union
Select Item='H', Parent='D'  
Go

...代表这个层次结构:

       A
     /   \
    B     C
   / \   / \
   D E   F G
  /
  H

所以 B 有一个祖先 (A),而 H 有 3 个祖先 (D,B,A)。这是所需的输出:

 Item | Ancestor
 B    | A
 C    | A
 D    | A
 D    | B
 E    | A
 E    | B
 F    | A
 F    | C
 G    | A
 G    | C
 H    | A
 H    | B
 H    | D

使用递归 CTE,我可以找到任何 ONE 项目的所有后代...

Create Function ItemDescendants(@Item char) Returns @result Table(Item char) As Begin
    ; With AllDescendants as (
        Select
            Item,
            Parent
        From Items i
        Where Item=@Item
        UNION ALL
        Select
            i.Item,
            i.Parent
        from Items i
        Join AllDescendants a on i.Parent=a.Item
    )
    Insert into @result (Item)
    Select Item from AllDescendants
    Where Item<>@Item;
    Return;
End
Go

...但是为了获得完整的扩展列表,我不得不求助于光标(yuk!):

Select Item, Parent into #t From Items

Declare @Item char
Declare c Cursor for (Select Item from Items)
Open c
Fetch c into @Item
While (@@Fetch_Status=0) Begin
    Insert into #t (Item, Ancestor) Select Item, @Item from dbo.ItemDescendants(@Item) 
    Fetch c into @Item
End
Close c
Deallocate c

Select Distinct
    Item,
    Ancestor
From #t
Where Parent is not null
Order by Item,Parent

Drop Table #t

这行得通,但如果我能用一个优雅的查询来做到这一点,我会更开心。似乎应该是可能的 - 有什么想法吗?

【问题讨论】:

    标签: sql recursion sql-server-2012 hierarchy common-table-expression


    【解决方案1】:

    假设我理解正确,它应该像从叶节点向后递归一样简单(这很容易,因为表 Items 只存储叶节点):

    ;with AncestryTree as (
      select Item, Parent
      from Items
      where Parent is not null
      union all
      select Items.Item, t.Parent  
      from AncestryTree t 
      join Items on t.Item = Items.Parent
     )
    select * from AncestryTree
    order by Item, Parent
    

    SQL Fiddle demo

    【讨论】:

      猜你喜欢
      • 2021-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-19
      • 2020-07-27
      • 1970-01-01
      相关资源
      最近更新 更多