Перечислите все предки или родительские узлы определенного узла, присутствующего на каждом уровне, в сводной таблице, содержащей уровни в качестве атрибутов SQL Server - PullRequest
0 голосов
/ 08 марта 2020

У меня есть таблица 'temp', в которой столбцы имеют идентификатор и идентификатор его непосредственного родителя. Таблица выглядит следующим образом:

temp table

                              1
                            /   \
                           2     3
                          /|\     \
                         4 5 6     7
                        /
                       8

Иерархия узлов может быть представлена ​​в древовидной структуре, как указано выше.

Теперь я хочу перечислить все предки или родительские узлы каждого узла, присутствующего на всех уровнях в сводной таблице, используя рекурсивный cte , который имеет уровни (например, Level1, Level2 и т. Д.) Как его атрибуты. Чтобы получить этот вывод, я вычислил все родительские узлы в неповоротной таблице с уровнем каждого узла относительно его родителя. sql запрос, для которого ниже:

WITH ctetable as 
(
    SELECT S.id, S.parent, 1 as level
    FROM temp as S where S.parent is not null
    UNION ALL
    SELECT S2.id, p.parent, p.level + 1
    FROM ctetable AS p JOIN temp as S2 on S2.parent = p.id
)
SELECT * FROM ctetable ORDER BY id;

Вывод вышеуказанного запроса показан ниже:

cte output

Но Я хочу развернуть рекурсивный cte, который содержит родительский идентификатор на каждом уровне определенного узла. Скажем, для id = 4 он должен отображать родительские идентификаторы 4, 2 и 1 под Level3, Level2 и Level1 соответственно. Для этого я написал следующий запрос:

WITH ctetable as 
(
    SELECT S.id, S.parent, 1 as level
    FROM temp as S where S.parent is not null
    UNION ALL
    SELECT S2.id, p.parent, p.level + 1
    FROM ctetable AS p JOIN temp as S2 on S2.parent = p.id
)

SELECT      
            myid,
            [pn].[1] AS [Level1],
            [pn].[2] AS [Level2],
            [pn].[3] AS [Level3] 
FROM
     (
         SELECT [a].id,
                [a].id as myid,
                [a].level
         FROM ctetable AS [a]
     ) AS [hn] PIVOT(max([hn].id) FOR [hn].level IN([1],[2],[3])) AS [pn]

Но выходная таблица не является желаемой, так как она содержит тот же идентификатор, повторяемый как родительский идентификатор на каждом уровне для определенного узла, вместо этого она должна содержать все родители этого узла под различными уровнями. Вывод, который я получил после выполнения вышеуказанного запроса, показан ниже:

main output

Может кто-нибудь помочь мне с этим ....

1 Ответ

1 голос
/ 08 марта 2020

Если у вас есть известное или максимальное количество уровней и предполагается, что я не изменил желаемые вами результаты.

Также Лучше всего, если вы публикуете данные образца и желаемые результаты в виде текста, а не как изображение

Пример

Declare @YourTable Table ([id] int,[parent] int)
Insert Into @YourTable Values 
 (1,null)
,(2,1)
,(3,1)
,(7,3)
,(4,2)
,(5,2)
,(6,2)
,(8,4)

;with cteP as (
      Select id
            ,Parent 
            ,PathID = cast(10000+id as varchar(500))
      From   @YourTable
      Where  Parent is Null
      Union  All
      Select id  = r.id
            ,Parent  = r.Parent 
            ,PathID = cast(concat(p.PathID,',',10000+r.id) as varchar(500))
      From   @YourTable r
      Join   cteP p on r.Parent  = p.id)
Select ID
      ,B.*
 From  cteP A
 Cross Apply (
                Select Level1 = xDim.value('/x[1]','int')-10000
                      ,Level2 = xDim.value('/x[2]','int')-10000
                      ,Level3 = xDim.value('/x[3]','int')-10000
                      ,Level4 = xDim.value('/x[4]','int')-10000
                      ,Level5 = xDim.value('/x[5]','int')-10000
                From  (Select Cast('<x>' + replace(PathID,',','</x><x>')+'</x>' as xml) as xDim) as X 
             ) B
  Order By PathID

Возвращает

enter image description here

РЕДАКТИРОВАТЬ - Добавлено + 10000

Я добавил +10000, чтобы сохранить последовательность

...