Recursive query for hirarchical data based on adjacency list

后端 未结 2 327
我在风中等你
我在风中等你 2021-01-16 09:58

Learing SQL, and have a bit of a problem. I have 2 tables level and level_hierarchy

|name        | id |     |parent_id | child_id|
         


        
相关标签:
2条回答
  • 2021-01-16 10:32

    Your query for the first level (here depth to distinguish from the table) should look like this:

    select l.name, h.child_id, 1 as depth 
    from level l
    join level_hierarchy h on l.id = h.child_id 
    where h.parent_id is null;
    
       name   | child_id | depth 
    ----------+----------+-------
     Level1_a |        1 |     1
    (1 row)
    

    Note the proper use of is null (do not use = to compare with null as it always gives null).

    You can use the above as an initial query in a recursive cte:

    with recursive recursive_query as (
        select l.name, h.child_id, 1 as depth 
        from level l
        join level_hierarchy h on l.id = h.child_id 
        where h.parent_id is null
    union all
        select l.name, h.child_id, depth + 1
        from level l
        join level_hierarchy h on l.id = h.child_id
        join recursive_query r on h.parent_id = r.child_id
    )
    select *
    from recursive_query
    -- where depth = 2
    
       name   | child_id | depth 
    ----------+----------+-------
     Level1_a |        1 |     1
     Level2_b |        3 |     2
     Level2_a |       19 |     2
     Level3_a |        4 |     3
     Level3_b |        5 |     3
     Level4_a |        6 |     4
     Level4_b |        7 |     4
    (7 rows)    
    
    0 讨论(0)
  • 2021-01-16 10:46

    Good question, recursion is a difficult topic in SQL and its implementation varies by engine. Thanks for tagging your post with PostgreSQL. PostgreSQL has some excellent documentation on the topic.

    WITH RECURSIVE rec_lh(child_id, parent_id) AS (
        SELECT child_id, parent_id FROM level_hierarchy
      UNION ALL
        SELECT lh.child_id, lh.parent_id
        FROM rec_lh rlh INNER JOIN level_hierarchy lh
          ON lh.parent_id = rlh.child_id
      )
    SELECT DISTINCT level.name, child_id 
    FROM rec_lh INNER JOIN level
      ON rec_lh.parent_id = level.id
    ORDER BY level.name ASC;
    

    See Also:

    Recursive query in PostgreSQL. SELECT *

    0 讨论(0)
提交回复
热议问题