Skip to content
Advertisement

Table recursive lookup on itself

I have the following table below.

I want to select all of the members of Group-D

SELECT * FROM mytable
where grp = "Group-D"

However, Group-D also contains Group-C along with User 5. Group-C contains Group-A and Group-B.

So, the select should return:

User-1
User-2
User-3
User-4
User-5
Group-A
Group-B
Group-C

Obviously, without doing multiple lookups on itself, I will not get that output.

How can I make the select statement do a table lookup within itself like that?

grp member
Group-A User-1
Group-A User-2
Group-B User-3
Group-B User-4
Group-C Group-A
Group-C Group-B
Group-D Group-C
Group-D User-5
Group-E User-6

Advertisement

Answer

The following recursive CTE will traverse through the data to arrive at parent/child relationships:

declare @value as varchar(40)
set @value = 'Group-D'

;with CTE as (
        select 1 as lvl, @value as member, cast(null as varchar(40)) as parent
        union all                  
        select CTE.lvl + 1, t.member, t.grp
        from CTE
        inner join mytable as t on CTE.member = t.grp
        where lvl < 10 
        )
select
    lvl, member, parent
from CTE
order by lvl, member

result

+-----+---------+---------+
| lvl | member  | parent  |
+-----+---------+---------+
|   1 | Group-D |         |
|   2 | Group-C | Group-D |
|   2 | User-5  | Group-D |
|   3 | Group-A | Group-C |
|   3 | Group-B | Group-C |
|   4 | User-1  | Group-A |
|   4 | User-2  | Group-A |
|   4 | User-3  | Group-B |
|   4 | User-4  | Group-B |
+-----+---------+---------+

See this working at db<>fiddle

Note, I introduced “lvl” as a way to implement an “escape” from the recursion – “just in case”

Also, if you don’t want to include the top level item in the result, use

select
    lvl, member, parent
from CTE
where parent IS NOT NULL
order by lvl, member

and you could commence lvl as zero instead of 1 in the CTE

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement