也许比需要多一点,但考虑以下:
您可以设置顶级节点(空默认为整个层次结构)
您还可以设置过滤器。对于没有过滤器,单个ID或ID的分隔字符串,这可以为空。
Declare @T table (id int,nameVal varchar(50),parentId int)
Insert into @T values
(1 ,'A', NULL),
(2 ,'B', NULL),
(3 ,'C', NULL),
(4 ,'D', NULL),
(5 ,'E', NULL),
(6 ,'A1', 1),
(7 ,'A2', 6),
(8 ,'A3', 1),
(9 ,'A4', 7),
(10 ,'B1', 2),
(11 ,'B2', 2)
Declare @Top int = null --<< Sets top of Hier Try 6
Declare @Nest varchar(25) = '|-----' --<< Optional: Added for readability
Declare @Filter varchar(25) = '7' --<< Empty for All or try '7,10'
;with cteP as (
Select Seq = cast(10000+Row_Number() over (Order by nameVal) as varchar(500))
,ID
,parentId
,Lvl=1
,nameVal
From @T
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.nameVal)) as varchar(500))
,r.ID
,r.parentId
,p.Lvl+1
,r.nameVal
From @T 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.Seq,A.ID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.ID)
,cte as (
Select A.R1
,B.R2
,A.ID
,A.parentId
,A.Lvl
,nameVal = Replicate(@Nest,A.Lvl-1) + A.nameVal
From cteR1 A
Join cteR2 B on A.ID=B.ID
)
Select Distinct A.*
From cte A
Join (
Select A.R1,A.R2
From cte A
Join (Select R1 from cte Where IIF(@Filter='',1,0)+CharIndex(concat(',',ID,','),concat(',',@Filter+','))>0) B
on B.R1 between A.R1 and A.R2
) B on A.R1 between B.R1 and B.R2
Order By A.R1
返回
现在,如果你设置@Filter = '7,10'
,你会得到
如果设置@Filter = ''
,你会得到
看看公用表表达式(CTE)。如果你想在同一个查询中同时使用父和子关系(但是可行),那么这么做是非常重要的。请参阅http://stackoverflow.com/q/4740748/67392。 – Richard