Отображать родительский элемент верхней иерархии для ребенка - PullRequest
0 голосов
/ 21 сентября 2019

У меня есть таблица с родительскими дочерними отношениями, и я хочу, чтобы для каждого дочернего элемента отображался самый верхний родительский элемент.Порядок реальной таблицы не будет упорядочен настолько последовательно, поэтому любой вид сортировки нежелателен.Я также хочу избегать ручных объединений для максимального числа уровней иерархии.

Таблица:

Parent  Child
1       2
2       3
3       4
5       6
6       7

Таким образом, для ребенка 4 есть родитель 3, у которого есть родитель 2, у которого есть родитель 14, 3, 2 все должны иметь Родителя 4. на выходе.

Желаемый вывод:

Parent       Child
1            2
1            3
1            4
5            6
5            7

Ответы [ 2 ]

1 голос
/ 21 сентября 2019

Рекурсивное Общее Табличное Выражение (CTE) позволяет быстро пройтись по иерархии родителей / потомков.Этот пример начинается с родителей верхнего уровня, то есть строк, над которыми нет родителей.Затем он добавляет детей по одному уровню за раз, следя за верхним родителем.

-- Sample data.
declare @Samples as Table ( Parent Int, Child Int );
insert into @Samples ( Parent, Child ) values
  ( 1, 2 ), ( 2, 3 ), ( 3, 4 ), ( 5, 6 ), ( 6, 7 );
select * from @Samples;

-- Run the tree.
with Tree as (
  -- Start with the top level parents.
  select Parent as TopLevelParent, Child
    from @Samples as S
    -- Where the row has no parent above it.
    where not exists ( select 42 from @Samples as SS where S.Parent = SS.Child )
  union all
  -- Add the children one level at a time.
  select T.TopLevelParent, S.Child
    from Tree as T inner join
      @Samples as S on S.Parent = T.Child )
  -- Display the sorted results.
  select TopLevelParent, Child
    from Tree
    order by TopLevelParent, Child;
1 голос
/ 21 сентября 2019
;with SelectedToTopCTE as
  ( select ParentID, ChildID as Child, 1 as level
    from Table
  union all
    select d.ParentID, s.ChildID, d.level + 1
    from SelectedToTopCTE as d
      join Table s
        on d.Child = s.ParentID
  ) 
select * INTO #SelectedToTop
from SelectedToTopCTE;

SELECT Child, MAX(level) as MaxLevel INTO #UpperMostSPLT
FROM #SelectedToTop
group by Child;

SELECT A.* 
FROM #SelectedToTop A
INNER JOIN
#UpperMostSPLT B
ON A.Child = B.Child AND A.level = B.MaxLevel
ORDER BY ParentID;
...