Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the parent given a child in SQL SERVER 2005

I have a table like this

childid      parentid
------------------------
1       0
2       1
3       2
4       2
5       3
6       4
7       0
8       7
9       8
10      1

If I give a childid as 5, the parentid will be 1(output)

If I give a childid as 9, the parentid will be 7.(output)

i.e. the root parentid is 0 and the query should stop there.

How to solve such a query?

Please help.

like image 629
priyanka.sarkar Avatar asked Jan 20 '26 09:01

priyanka.sarkar


1 Answers

I think you should rename your child_id to node, your parent_id to child_of. Your column naming is a bit confusing

create table stack_overflow
(
node int, child_of int
);


insert into stack_overflow(node, child_of) values
(1,0),
(2,1),
(3,2),
(4,2),
(5,3),
(6,4),
(7,0),
(8,7),
(9,8),
(10,1);

This works on any CTE-capable RDBMS:

with find_parent(parent, child_of, recentness) as
(
    select node, child_of, 0 
    from stack_overflow
    where node = 9
    union all
    select i.node, i.child_of, fp.recentness + 1
    from stack_overflow i
    join find_parent fp on i.node = fp.child_of
)
select top 1 parent from find_parent 
order by recentness desc

Output:

parent
7

[EDIT: more flexible and future-proof]:

with find_parent(node_group, parent, child_of, recentness) as
(
    select node, node, child_of, 0
    from stack_overflow
    where node in (5,9)
    union all
    select fp.node_group, i.node, i.child_of, fp.recentness + 1
    from stack_overflow i
    join find_parent fp on i.node = fp.child_of
)
select q.node_group as to_find, parent as found 
from find_parent q 
join
(
    select node_group, max(recentness) as answer
    from find_parent
    group by node_group 
) as ans on q.node_group = ans.node_group and q.recentness = ans.answer 
order by to_find    

Output:

to_find     found
5           1
9           7

If you're using Postgres, the above code could be shortened to:

with recursive find_parent(node_group, parent, child_of, recentness) as
(
    select node, node, child_of, 0
    from stack_overflow
    where node in (5,9)
    union all
    select fp.node_group, i.node, i.child_of, fp.recentness + 1
    from stack_overflow i
    join find_parent fp on i.node = fp.child_of
)
select distinct on (node_group) node_group as to_find, parent as found 
from find_parent 
order by to_find, recentness desc

DISTINCT ON rocks! :-)

like image 132
Michael Buen Avatar answered Jan 22 '26 18:01

Michael Buen