基于邻接表递归查询分层数据
Recursive query for hirarchical data based on adjacency list
正在学习SQL,有点问题。我有 2 tables level
和 level_hierarchy
|name | id | |parent_id | child_id|
------------------- ---------------------
| Level1_a | 1 | | NULL | 1 |
| Level2_a | 19 | | 1 | 19 |
| Level2_b | 3 | | 1 | 3 |
| Level3_a | 4 | | 3 | 4 |
| Level3_b | 5 | | 3 | 5 |
| Level4_a | 6 | | 5 | 6 |
| Level4_b | 7 | | 5 | 7 |
现在我需要的是一个查询,它将 return 来自 table level
的所有条目,来自每个层次结构级别,基于标记我想要获得的层次结构级别的参数条目来自.
获取 Level1
个条目非常容易。
SELECT name FROM level INNER JOIN level_hierarchy ON level.id =
level_hierarchy.child_id WHERE level_hierarchy.parent_id=NULL
Level2
个条目:
Level2_a
Level2_b
只是那些有 parent 的人,他们 parent 的 parent 是 NULL
等等。这是我怀疑递归的地方。
有大神指导一下吗?
好问题,递归是 SQL 中的一个难题,其实现因引擎而异。感谢您使用 PostgreSQL 标记您的 post。 PostgreSQL 有一些优秀的 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;
另请参阅:
您的第一级查询(此处 depth
与 table 区别)应如下所示:
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)
注意 is null
的正确使用(不要使用 =
与 null
进行比较,因为它总是给出 null
)。
您可以将以上内容用作递归 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)
正在学习SQL,有点问题。我有 2 tables level
和 level_hierarchy
|name | id | |parent_id | child_id|
------------------- ---------------------
| Level1_a | 1 | | NULL | 1 |
| Level2_a | 19 | | 1 | 19 |
| Level2_b | 3 | | 1 | 3 |
| Level3_a | 4 | | 3 | 4 |
| Level3_b | 5 | | 3 | 5 |
| Level4_a | 6 | | 5 | 6 |
| Level4_b | 7 | | 5 | 7 |
现在我需要的是一个查询,它将 return 来自 table level
的所有条目,来自每个层次结构级别,基于标记我想要获得的层次结构级别的参数条目来自.
获取 Level1
个条目非常容易。
SELECT name FROM level INNER JOIN level_hierarchy ON level.id =
level_hierarchy.child_id WHERE level_hierarchy.parent_id=NULL
Level2
个条目:
Level2_a
Level2_b
只是那些有 parent 的人,他们 parent 的 parent 是 NULL
等等。这是我怀疑递归的地方。
有大神指导一下吗?
好问题,递归是 SQL 中的一个难题,其实现因引擎而异。感谢您使用 PostgreSQL 标记您的 post。 PostgreSQL 有一些优秀的 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;
另请参阅:
您的第一级查询(此处 depth
与 table 区别)应如下所示:
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)
注意 is null
的正确使用(不要使用 =
与 null
进行比较,因为它总是给出 null
)。
您可以将以上内容用作递归 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)