Question

I have following table:

create table osoba(
id int primary key,
idNd int,
nazwim nvarchar(500),
)

Data looks like below:

id  idNd    nazwim
1   NULL    grandpa
2   1   child1
3   1   child2
4   2   grandchild1child1
5   2   grandchild2child1
6   3   grandchild1child2
7   3   grandchild2child2

I've got following cte:

;WITH ret AS(
       SELECT   *
    FROM    osoba
    --WHERE   ID = 1
    UNION ALL
    SELECT o.*
    FROM    osoba o INNER JOIN
            ret r ON o.idNd = r.ID)

Select * from ret returns all descendants for each node and starting node:

id  idNd    nazwim
1   NULL    grandpa
2   1   child1
3   1   child2
4   2   grandchild1child1
5   2   grandchild2child1
6   3   grandchild1child2
7   3   grandchild2child2
6   3   grandchild1child2
7   3   grandchild2child2
4   2   grandchild1child1
5   2   grandchild2child1
2   1   child1
3   1   child2
6   3   grandchild1child2
7   3   grandchild2child2
4   2   grandchild1child1
5   2   grandchild2child1

How to retrieve information about starting node for each record? I would like to get result like that:

idStartingNode  id  idNd    nazwim
1   1   NULL    grandpa
1   2   1   child1
1   3   1   child2
1   4   2   grandchild1child1
1   5   2   grandchild2child1
1   6   3   grandchild1child2
1   7   3   grandchild2child2
3   6   3   grandchild1child2
3   7   3   grandchild2child2
2   4   2   grandchild1child1
2   5   2   grandchild2child1
2   2   1   child1
3   3   1   child2
6   6   3   grandchild1child2
7   7   3   grandchild2child2
4   4   2   grandchild1child1
5   5   2   grandchild2child1
Was it helpful?

Solution

You add the column, in both parts of the recursive CTE.

Starting nodes have the ID as startingNode id.

The descendants have as starting node id, the starting node id of their parent:

WITH ret AS
  (
    SELECT id AS idStartingNode, o.*
    FROM    osoba o
    --WHERE   ID = 1
    UNION ALL
    SELECT r.idStartingNode, o.*
    FROM    osoba o INNER JOIN
            ret r ON o.idNd = r.ID
  ) ;

OTHER TIPS

You also need level to get a meaningful report

declare @t table (id int primary key, idNd int, nazwim varchar(50));
insert @t values 
(1, NULL, 'grandpa'),
(2, 1, 'child1'),
(3, 1, 'child2'),
(4, 2, 'grandchild1child1'),
(5, 2, 'grandchild2child1'),
(6, 3, 'grandchild1child2'),
(7, 3, 'grandchild2child2');
--select * from @t;

with cte as 
(  select id as ori, id, idNd, nazwim, 1 as level
   from @t
   union all 
   select c.ori, t.id, t.idNd, t.nazwim, level + 1
   from cte c
   join @t t
     on t.idNd = c.id
)
select * 
from cte
order by ori, level;
Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top