我有一个类别表,其中包含parent_id字段.parent_id可以包含类别ID,因此我们知道它的子catgory。 parent_id = 0表示它是顶级类别
我想先编写一个查询按顶级类别排序,然后是该顶级类别的所有子类别,然后是该顶级类别的所有子类别。有没有人对此有任何想法。
由于
Sampe数据
CategoryId | CategoryName | Parent_id 1 cat A 0 2 cat B 0 3 cat C 0 4 cat D 0 5 cat A A 1 6 cat A B 1 7 cat A A A 5 8 cat A A B 5 9 cat B A 2 10 cat B B 2 11 cat B C 2 12 cat B D 2
结果应该是:
CategoryId | CategoryName | Parent_id 1 cat A 0 5 cat A A 1 7 cat A A A 5 8 cat A A B 5 6 cat A B 1 2 cat B 0 9 cat B A 2 10 cat B B 2 11 cat B C 2 12 cat B D 2 3 cat C 0 4 cat D 0
答案 0 :(得分:1)
Declare @YourTable table (categoryID int,CategoryName varchar(50),parent_id int)
Insert into @YourTable values
(1 ,'cat A', 0),
(2 ,'cat B', 0),
(3 ,'cat C', 0),
(4 ,'cat D', 0),
(5 ,'cat A A', 1),
(6 ,'cat A B', 1),
(7 ,'cat A A A',5),
(8 ,'cat A A B',5),
(9 ,'cat B A', 2),
(10,'cat B B', 2),
(11,'cat B C', 2),
(12,'cat B D', 2)
Declare @Top int = null --<< Sets top of Hier Try 5
Declare @Nest varchar(25) ='|-----' --<< Optional: Added for readability
;with ctePt as (
Select Seq = cast(1000+Row_Number() over (Order by CategoryName) as varchar(500))
,categoryID
,parent_id
,Lvl=1
,CategoryName
From @YourTable
Where IsNull(@Top,0) = case when @Top is null then isnull(parent_id,0) else categoryID end
Union All
Select Seq = cast(concat(p.Seq,'.',100000+Row_Number() over (Order by r.CategoryName)) as varchar(500))
,r.categoryID
,r.parent_id,p.Lvl+1
,r.CategoryName
From @YourTable r
Join ctePt p on r.parent_id = p.categoryID)
,cteR1 as (Select Seq,categoryID,R1=Row_Number() over (Order By Seq) From ctePt)
,cteR2 as (Select A.Seq,A.categoryID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.categoryID )
Select B.R1
,C.R2
,A.categoryID
,A.parent_id
,A.Lvl
,CategoryName = Replicate(@Nest,A.Lvl-1) + A.CategoryName
From ctePt A
Join cteR1 B on A.categoryID=B.categoryID
Join cteR2 C on A.categoryID=C.categoryID
Order By B.R1
返回
现在,您可能会注意到R1 / R2。这些是范围键。我发现它们在层次结构中导航和聚合数据时很有用。如果您不需要它们,请删除cteR1和cteR2并设置最终订单A.Seq
只是为了好玩,如果你设置@Top = 5,你就会