4

孩子我有喜歡這 -SqlServer的分層父/子查詢與排序裏面父

ID ParentID ProductTypeName 
1 NULL  Electronics 
200 1   TV 
300 200   Plasma 
67 NULL  KitchenAppliances 
78 67   Stoves 
82 78   Electric 
99 78   Gas 
23 200   LED 
65 300   LG 
66 300   Sony 

數據的表,我想獲得以下格式的數據 -

ID ParentID ProductTypeName   Level Sort(Or Some kind of sort value) 
1 NULL  Electronics    0  1 
200 1   TV      1  110 
300 200   LED      2  120 
65 300   LG      3  12010 
66 300   Sony     3  12020 
23 200   Plasma     2  100030 
67 NULL  KitchenAppliances  0  10000010 
78 67   Stoves     1  1000001010 
82 78   Electric    2  100000101020 
99 78   Gas      2  100000101030 

以這種格式顯示樹中的數據。請注意,每位家長的孩子也會被分類。縮進被賦予這樣可以給結果的一個更好的主意 -

Electronics 
    TV 
     LED 
      LG 
      Sony 
     Plasma 
KitchenAppliances 
    Stoves 
     Electric 
     Gas 

這是我寫的查詢,但似乎並不奏效。 排序編號邏輯似乎被打破。 有人可以幫忙。 任何幫助表示讚賞。謝謝。

;WITH cte (ID, ParentID, [Level], [Name], Sort) AS(
         SELECT  sc1.ID, 
            NULL, 
            0, 
            sc1.Name, 
            cast(row_number()over(partition by sc1.ParentCategoryID order by sc1.Name) as varchar(max)) as Sort 
         FROM TableData sc1 
         WHERE sc1.ID is null 
         UNION ALL 
         SELECT  sc2.ID, 
            sc2.ParentID, 
            g2.[level] + 1, 
            sc2.Name, 
            g2.Sort + cast(row_number()over(partition by sc2.ParentCategoryID order by sc2.Name) as varchar(max))Sort 
         FROM dbo.TableData sc2 
           INNER JOIN cte g2 
              ON sc2.ParentID = g2.ID 

回答

3

你這樣做幾乎是正確的。我唯一改變的是:改變WHERE sc1.ParentID is null CTE的非遞歸部分條件WHERE sc1.ID is null的方式,以及排序鍵(路徑)計算:

;WITH cte (ID, ParentID, [Name], Level, SortPath, DisplayPath) 
AS(
    SELECT sc1.ID, NULL, sc1.Name, 0, 
     cast(row_number() over (partition by sc1.ParentCategoryID order by sc1.Name) as varbinary(max)), 
     cast(row_number() over (partition by sc1.ParentCategoryID order by sc1.Name) as varchar(max)) 
    FROM dbo.TableData sc1 
    WHERE sc1.ParentID is null 
    UNION ALL 
    SELECT sc2.ID, sc2.ParentID, sc2.Name, g2.Level + 1 
     g2.SortPath + cast(row_number() over (partition by sc2.ParentCategoryID order by sc2.Name) as binary(4)), 
     g2.DisplayPath + '.' + cast(row_number() over (partition by sc1.ParentCategoryID order by sc1.Name) as varchar(10)) 
    FROM dbo.TableData sc2 
     JOIN cte g2 ON sc2.ParentID = g2.ID 
) 
select ID, ParentID, Name, DisplayPath 
from cte 
order by SortPath 

正如你所看到的,有計算的兩條路徑,第一個是對元素進行排序,第二個是查看。如果樹元素的路徑不應該在任何地方顯示,則可以只保留SortPath。

+1

爲了避免字母數字問題,最好將左邊的「DisplayPath」值填充爲零,以固定寬度。樣本數據集足夠小,以至於一位數字恰好可以工作。 – HABO

+0

@HABO,在這種情況下,它是故意的。 'DisplayPath'不應該用於排序。沒有領先的零點,它更友好觀看(如果有需要的話)。 'SortPath'是一種技術性的東西,它只用於排序操作。 –