Postgresql 分层(树)查询

Postgresql hierarchical (tree) query

我发现很少有关于它的主题,但 none 符合我的预期结果。 我在table中存储了类别的级别,只是想将其显示为树结构。 所有答案都是以下查询:

DB FIDDLE

WITH RECURSIVE cte AS (
   SELECT category_id, category_name, parent_category, 1 AS level
   FROM   category
   WHERE level = 1
   UNION  ALL
   SELECT c.category_id, c.category_name, c.parent_category, ct.level + 1
   FROM   cte ct
   JOIN   category c ON c.parent_category = ct.category_id
   )
SELECT *
FROM cte;

但是结果是这样的

level
1
1
2
2
2
3
3
3
3
3

我要实现的是

level
1
2
3
3
2
3
3
1
2
3
3
2
3
3

您通常会跟踪每个节点的路径并将其用于排序。在 Postgres 中,数组可以派上用场:

with recursive cte as (
   select category_id, category_name, parent_category, 1 as level, array[category_id] path
   from category
   where parent_category is null
   union all
   select c.category_id, c.category_name, c.parent_category, ct.level + 1, ct.path || c.category_id
   from cte ct
   join category c on c.parent_category = ct.category_id
)
select *
from cte
order by path

注意table中不需要存储level;您可以在迭代时即时计算信息。要识别根节点,您可以过滤父节点为 null.

的行

your db fiddle中查询returns:

category_id | category_name | parent_category | level | path    
----------: | :------------ | --------------: | ----: | :-------
          1 | cat1          |            null |     1 | {1}     
          3 | cat3          |               1 |     2 | {1,3}   
          8 | cat8          |               3 |     3 | {1,3,8} 
          9 | cat9          |               3 |     3 | {1,3,9} 
          4 | cat4          |               1 |     2 | {1,4}   
          6 | cat6          |               4 |     3 | {1,4,6} 
          7 | cat7          |               4 |     3 | {1,4,7} 
          5 | cat5          |               1 |     2 | {1,5}   
         10 | cat10         |               5 |     3 | {1,5,10}
         11 | cat11         |               5 |     3 | {1,5,11}
          2 | cat2          |            null |     1 | {2}     

您可以将层次结构作为数组进行跟踪并将其用于排序:

WITH RECURSIVE cte AS (
     SELECT category_id, category_name, parent_category, 1 AS level, array[category_id] as categories
     FROM category
     WHERE level = 1
     UNION ALL
     SELECT c.category_id, c.category_name, c.parent_category, ct.level + 1, ct.categories || c.category_id
     FROM cte ct JOIN
          category c
          ON c.parent_category = ct.category_id
    )
SELECT *
FROM cte
ORDER BY categories;

Here 是一个 db<>fiddle.