我有一个简单的层次结构,需要能够生成一个与所有祖先表相匹配的表的单个表。(要强调这不是重复的问题!)
所以这是一张表:
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,我能够找到任何一项的所有后代…
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
这行得通,但是如果我能用一个优雅的查询做到这一点,我就会非常高兴。似乎应该有可能-有什么想法吗?
假设我理解正确,它应该像从叶节点向后递归一样简单(这很容易,因为表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演示