如何在使用递归到 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 连接中交换了 idparent_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)

Db<>fiddle.