Postgresql 分层(树)查询
Postgresql hierarchical (tree) query
我发现很少有关于它的主题,但 none 符合我的预期结果。
我在table中存储了类别的级别,只是想将其显示为树结构。
所有答案都是以下查询:
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.
我发现很少有关于它的主题,但 none 符合我的预期结果。 我在table中存储了类别的级别,只是想将其显示为树结构。 所有答案都是以下查询:
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.