Home > Enterprise >  Recursive Self-Join in postgres
Recursive Self-Join in postgres

Time:01-22

I have a table of profiles that have data related to the managers of a user.

There can multiple levels of managers for a user.

I need to write a query to get all the managers of a user.

Official manager_id is stored in column text = A.

Table Name profiles

id text manager_id user_id
1 A 20 50
2 B 20 50
3 A 21 20
4 B NULL 20
5 C NULL 20
6 A 22 21
7 B NULL 21
9 A NULL 22

For example,

If user_id=50 then,
50 manager's is 20
20 manager's is 21
21 manager's is 22
21 manager's is NULL
So, the output should be 20,21,22

Similarly, if user_id=20 the output should be 21,22

I tried a couple of queries but it doesn't return the expected output.

CodePudding user response:

The recursive query you're looking for should feature:

  • base step, which begins with distinct couples of user_id and manager_id from the input table
  • recursive step, which self joins the table with the current recursive result, matching manager of the second to be users of the first

Once you get all matches, you can aggregate your values by "user_id" with ARRAY_AGG.

WITH RECURSIVE cte AS (
    SELECT DISTINCT user_id, manager_id 
    FROM tab 
    WHERE manager_id IS NOT NULL
  
    UNION ALL
  
    SELECT usr.user_id,
           mgr.manager_id
    FROM       cte usr
    INNER JOIN tab mgr
            ON usr.manager_id = mgr.user_id
    WHERE mgr.manager_id IS NOT NULL
)
SELECT user_id, 
       ARRAY_AGG(manager_id) AS managers
FROM cte 
GROUP BY user_id

Check the demo here.

  • Related