Reputation: 326
I have a table with parent child relationships and I want to, for each child, display the upper most parent. The order of the real table won't be ordered so consecutively so any kind of sorting isn't desirable. I also want to avoid doing manual joins for the max number of hierarchy levels.
Table:
Parent Child
1 2
2 3
3 4
5 6
6 7
So for Child 4 has Parent 3, who has Parent 2, who has Parent 1. 4, 3, 2 should all have Parent 4 in the output.
Desired Output:
Parent Child
1 2
1 3
1 4
5 6
5 7
Upvotes: 0
Views: 173
Reputation: 15816
A recursive Common Table Expression (CTE) makes quick work of walking through parent/child hierarchies. This example starts with the top level parents, i.e. the rows that have no parents above them. It then adds children one level at a time while keeping track of the topmost parent.
-- 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;
Upvotes: 1
Reputation: 326
;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;
Upvotes: 1