declare @t table
(
id int,
ancestor_id int,
descendant_id int,
depth int,
type int
);
insert into @t(id, ancestor_id, descendant_id, depth, type)
values
(207 , 86 , 86 , 0 , 1),
(208 , 87 , 87 , 0 , 1),
(209 , 86 , 87 , 1 , 1),
(210 , 88 , 88 , 0 , 1),
(211 , 86 , 88 , 2 , 1),
(212 , 87 , 88 , 1 , 1),
(213 , 89 , 89 , 0 , 1),
(214 , 87 , 89 , 1 , 1),
(215 , 86 , 89 , 2 , 1),
(216 , 90 , 90 , 0 , 1),
(217 , 86 , 90 , 1 , 1),
(218 , 91 , 91 , 0 , 1),
(219 , 86 , 91 , 1 , 1),
(220 , 92 , 92 , 0 , 1),
(221 , 90 , 92 , 1 , 1),
(222 , 86 , 92 , 2 , 1),
(223 , 93 , 93 , 0 , 1),
(224 , 90 , 93 , 1 , 1),
(225 , 86 , 93 , 2 , 1);
with cte
as
(
select ancestor_id as childid, cast(null as int) as parentid, ancestor_id as rootid, 0 as lvl
from
(
--roots, top level parents (they are not chilren/descendants)
select ancestor_id
from @t
except
select descendant_id
from @t
where descendant_id <> ancestor_id
) as p
union all
select t.descendant_id, t.ancestor_id, c.rootid, c.lvl+1
from cte as c
join @t as t on c.childid = t.ancestor_id and t.ancestor_id <> t.descendant_id
)
select *
from cte;
--the full hierarchy of each child is logged in @t, for each parent get the list of children without cte
select ancestor_id as parentid, stuff(c.children_concat, 1, 1, '') as children_list
from
(
--parents
select distinct ancestor_id
from @t
) as p
outer apply
(
select
(
select distinct ',' + cast(t.descendant_id as varchar(20))
from @t as t
where t.ancestor_id = p.ancestor_id
and t.descendant_id <> p.ancestor_id
order by ',' + cast(t.descendant_id as varchar(20)) --desc
for xml path('')
) as children_concat
) as c;