如何在使用递归到 select 后代的 Postgres 查询中打印深度级别?
How does one print depth-level in a Postgres query that uses RECURSIVE to select descendants?
我有一个 table persons
,其中包含 parent_id
的列,它引用同一 table 中的另一行。假设这是逻辑层次结构:
P1
P2 P3 P4
P5 P6 P7 P8 P9 P10
我写了一个查询,打印给定节点的所有父节点,以及节点上方的高度,它似乎工作正常:
WITH
RECURSIVE ancestors AS (
SELECT id, parent_id
FROM persons
WHERE id = 8
UNION
SELECT p.id, p.parent_id
FROM persons p
INNER JOIN ancestors
ON
p.id = ancestors.parent_id
)
SELECT persons.id, persons.name,
ROW_NUMBER() over () as height
FROM ancestors
INNER JOIN persons
ON
ancestors.id = persons.id
WHERE
persons.id <> 8
结果:
id | name | height
-------+-------------+---------
3 | P3 | 1
1 | P1 | 2
(2 rows)
我现在想编写一个类似地打印所有后代以及深度的查询。这是到目前为止的查询(与上面相同,在 UNION 连接中交换了 id
和 parent_id
):
WITH
RECURSIVE descendants AS (
SELECT id, parent_id
FROM persons
WHERE id = 1
UNION
SELECT p.id, p.parent_id
FROM persons p
INNER JOIN descendants
ON
p.parent_id = descendants.id
)
SELECT persons.id, persons.name,
ROW_NUMBER() over () as depth
FROM descendants
INNER JOIN persons
ON
descendants.id = persons.id
WHERE
persons.id <> 1
结果如下:
id | name | depth
-------+-------------+---------
2 | P2 | 1
3 | P3 | 2
4 | P4 | 3
5 | P5 | 4
6 | P6 | 5
7 | P7 | 6
8 | P8 | 7
9 | P9 | 8
10 | P10 | 9
(9 rows)
很明显,深度全错了。 ROW_NUMBER()
没有按照我的意愿行事。我该怎么做?
我考虑过在查询本身的递归部分使用一个计数器,它每次递增 运行,但我不确定是否有办法实现它。
使用一个额外的整数列,其值在每个递归步骤递增。
WITH RECURSIVE descendants AS (
SELECT id, parent_id, 0 AS depth
FROM persons
WHERE id = 1
UNION
SELECT p.id, p.parent_id, d.depth+ 1
FROM persons p
INNER JOIN descendants d
ON p.parent_id = d.id
)
SELECT p.id, p.name, depth
FROM descendants d
INNER JOIN persons p
ON d.id = p.id
WHERE p.id <> 1;
id | name | depth
----+------+-------
2 | P2 | 1
3 | P3 | 1
4 | P4 | 1
5 | P5 | 2
6 | P6 | 2
7 | P7 | 2
8 | P8 | 2
9 | P9 | 2
10 | P10 | 2
(9 rows)
我有一个 table persons
,其中包含 parent_id
的列,它引用同一 table 中的另一行。假设这是逻辑层次结构:
P1
P2 P3 P4
P5 P6 P7 P8 P9 P10
我写了一个查询,打印给定节点的所有父节点,以及节点上方的高度,它似乎工作正常:
WITH
RECURSIVE ancestors AS (
SELECT id, parent_id
FROM persons
WHERE id = 8
UNION
SELECT p.id, p.parent_id
FROM persons p
INNER JOIN ancestors
ON
p.id = ancestors.parent_id
)
SELECT persons.id, persons.name,
ROW_NUMBER() over () as height
FROM ancestors
INNER JOIN persons
ON
ancestors.id = persons.id
WHERE
persons.id <> 8
结果:
id | name | height
-------+-------------+---------
3 | P3 | 1
1 | P1 | 2
(2 rows)
我现在想编写一个类似地打印所有后代以及深度的查询。这是到目前为止的查询(与上面相同,在 UNION 连接中交换了 id
和 parent_id
):
WITH
RECURSIVE descendants AS (
SELECT id, parent_id
FROM persons
WHERE id = 1
UNION
SELECT p.id, p.parent_id
FROM persons p
INNER JOIN descendants
ON
p.parent_id = descendants.id
)
SELECT persons.id, persons.name,
ROW_NUMBER() over () as depth
FROM descendants
INNER JOIN persons
ON
descendants.id = persons.id
WHERE
persons.id <> 1
结果如下:
id | name | depth
-------+-------------+---------
2 | P2 | 1
3 | P3 | 2
4 | P4 | 3
5 | P5 | 4
6 | P6 | 5
7 | P7 | 6
8 | P8 | 7
9 | P9 | 8
10 | P10 | 9
(9 rows)
很明显,深度全错了。 ROW_NUMBER()
没有按照我的意愿行事。我该怎么做?
我考虑过在查询本身的递归部分使用一个计数器,它每次递增 运行,但我不确定是否有办法实现它。
使用一个额外的整数列,其值在每个递归步骤递增。
WITH RECURSIVE descendants AS (
SELECT id, parent_id, 0 AS depth
FROM persons
WHERE id = 1
UNION
SELECT p.id, p.parent_id, d.depth+ 1
FROM persons p
INNER JOIN descendants d
ON p.parent_id = d.id
)
SELECT p.id, p.name, depth
FROM descendants d
INNER JOIN persons p
ON d.id = p.id
WHERE p.id <> 1;
id | name | depth
----+------+-------
2 | P2 | 1
3 | P3 | 1
4 | P4 | 1
5 | P5 | 2
6 | P6 | 2
7 | P7 | 2
8 | P8 | 2
9 | P9 | 2
10 | P10 | 2
(9 rows)