4

У меня есть таблица с данными, как this-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.ID is null в нерекурсивна части КТР изменено на WHERE sc1.ParentID 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' - это своего рода техническая вещь, предназначенная только для сортировки. –