按顶级类别的SQL查询顺序遵循子类别

时间:2016-12-20 19:50:36

标签: sql sql-server

我有一个类别表,其中包含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

1 个答案:

答案 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

返回

enter image description here

现在,您可能会注意到R1 / R2。这些是范围键。我发现它们在层次结构中导航和聚合数据时很有用。如果您不需要它们,请删除cteR1和cteR2并设置最终订单A.Seq

  

只是为了好玩,如果你设置@Top = 5,你就会

enter image description here