Как мне объединить несколько родительско-дочерних отношений разной длины с помощью T-SQL? - PullRequest
2 голосов
/ 21 мая 2019

Сводка

В базе данных Azure (с использованием SQL Server Management Studio 17, т. Е. T-SQL) я пытаюсь объединить несколько родительско-дочерних отношений различной длины.

Базовая таблица

Моя таблица имеет такую ​​форму:

ID   parent
1    2
2    NULL
3    2
4    3
5    NULL

Не стесняйтесь использовать этот код для генерации и заполнения:

DECLARE @t TABLE (
ID int,
parent int
)

INSERT @t VALUES
( 1, 2 ),
( 2, NULL ),
( 3, 2 ),
( 4, 3 ),
( 5, NULL )

Проблема

Как получить таблицу с конкатенацией путей, как показано в следующей таблице?

ID   path      parentcount
1    2->1      1
2    2         0
3    2->3      1
4    2->3->4   2
5    5         0

Сведения

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

select @@version:
Microsoft SQL Azure (RTM) - 12.0.2000.8

Ответы [ 2 ]

5 голосов
/ 21 мая 2019

Для этого вы можете использовать рекурсивный CTE:

with cte as (
      select id, parent, convert(varchar(max), concat(id, '')) as path, 0 as parentcount
      from @t t
      union all
      select cte.id, t.parent, convert(varchar(max), concat(t.id, '->', path)), parentcount + 1
      from cte join
           @t t
           on cte.parent = t.id
     )
select top (1) with ties *
from cte
order by row_number() over (partition by id order by parentcount desc);
1 голос
/ 21 мая 2019

Очевидно, что Гордон прибил его рекурсивным CTE, но вот еще один вариант, использующий тип данных HierarchyID.

Пример

Declare @YourTable Table ([ID] int,[parent] int)  
Insert Into @YourTable Values 
 (1,2)
,(2,NULL)
,(3,2)
,(4,3)
,(5,NULL)

;with cteP as (
      Select ID
            ,Parent 
            ,HierID = convert(hierarchyid,concat('/',ID,'/'))
      From   @YourTable 
      Where  Parent is Null
      Union  All
      Select ID     = r.ID
            ,Parent = r.Parent 
            ,HierID = convert(hierarchyid,concat(p.HierID.ToString(),r.ID,'/'))
      From   @YourTable r
      Join   cteP p on r.Parent  = p.ID
)
Select ID
      ,Parent
      ,[Path]      = HierID.GetDescendant ( null , null ).ToString()   
      ,ParentCount = HierID.GetLevel() - 1
 From cteP A
 Order By A.HierID

Returns

enter image description here

...