如果您的层次结构移动缓慢,请考虑添加范围键。它们有助于导航、过滤和/或聚合,而不需要递归。
Range 键表示 X 和 Y 之间的所有权。在处理大型层次结构(180K 节点)时,范围键特别有用。
以下是一个简化的示例,但可能会有所帮助。
样本层次构建
--Drop Table #MyHier
Declare @YourTable table (id int,ParentId int,Name varchar(50))
Insert into @YourTable values
(11, NULL,'A')
,(12, 11 ,'B')
,(13, 12 ,'F')
,(14, 13 ,'C')
,(15, 13 ,'D')
,(16, 11 ,'E')
,(17, 12 ,'G')
,(18, NULL ,'M')
,(19, 18 ,'N')
,(20, 18 ,'O')
,(21, 20 ,'P')
Declare @Top int = null --<< Sets top of Hier Try 3
Declare @Nest varchar(25) = '|-----' --<< Optional: Added for readability
;with cteP as (
Select Seq = cast(10000+Row_Number() over (Order by Name) as varchar(500))
,ID
,ParentId
,Lvl=1
,Name
,Path = cast('/'+Name+'/' as varchar(500))
From @YourTable
Where IsNull(@Top,-1) = case when @Top is null then isnull(ParentId ,-1) else ID end
Union All
Select Seq = cast(concat(p.Seq,'.',10000+Row_Number() over (Order by r.Name)) as varchar(500))
,r.ID
,r.ParentId
,p.Lvl+1
,r.Name
,cast(p.path + '/'+r.Name+'/' as varchar(500))
From @YourTable r
Join cteP p on r.ParentId = p.ID)
,cteR1 as (Select *,R1=Row_Number() over (Order By Seq) From cteP)
,cteR2 as (Select A.ID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.ID )
Select A.R1
,B.R2
,A.ID
,A.ParentId
,A.Lvl
,Name = Replicate(@Nest,A.Lvl-1) + A.Name
,Path
Into #MyHier
From cteR1 A
Join cteR2 B on A.ID=B.ID
选择全层
-- Get The Full Hier
Select *
From #MyHier
Order By R1
退货
获取祖先
-- Get Ancestors of a Node
Declare @GetAncestors int = 15
Select A.*
From #MyHier A
Join (Select R1 From #MyHier Where ID=@GetAncestors) B
on B.R1 between A.R1 and A.R2
Order By A.R1
退货
选择后代
-- Get Descendants of a Node
Declare @GetDesendants int = 12
Select A.*
From #MyHier A
Join (Select R1,R2 From #MyHier Where ID=@GetDesendants) B
on A.R1 between B.R1 and B.R2
Order By A.R1
退货