如何在PostgreSQL中选择具有级别的表的所有层次结构

如何在PostgreSQL中选择具有级别的表的所有层次结构,sql,postgresql,hierarchical-data,recursive-query,Sql,Postgresql,Hierarchical Data,Recursive Query,我现在有个问题。 我有一张名为places的桌子,其结构如下: 身份证 家长id 名字 我想做一个选择,以拥有此表的所有层次结构。这里有一个数据的小例子: (1, null, '123 Barclay St') (2, 1, 'Floor 1') (3, 1, 'Floor 2') (4, 1, 'Floor 3') (5, 2, 'Hall 1') (6, 2, 'Room 1') (7, 2, 'Room 2') (8, 3, 'Room 3') (9, null, '10 Thames

我现在有个问题。 我有一张名为places的桌子,其结构如下:

  • 身份证
  • 家长id
  • 名字
我想做一个选择,以拥有此表的所有层次结构。这里有一个数据的小例子:

(1, null, '123 Barclay St')
(2, 1, 'Floor 1')
(3, 1, 'Floor 2')
(4, 1, 'Floor 3')
(5, 2, 'Hall 1')
(6, 2, 'Room 1')
(7, 2, 'Room 2')
(8, 3, 'Room 3')
(9, null, '10 Thames St')
显然,表中的顺序不是这个

所以我想通过我的SELECT(9行)得到这个结果:

而不是这个结果(我已经知道如何得到):


如果您能帮助我,我将提前感谢您。

这里有一个使用递归CTE的解决方案:

WITH RECURSIVE cte AS (
    SELECT LPAD(id::text, 3, '0') AS marker, '   ' AS buffer,
        id, parent_id, name::text
    FROM yourTable t WHERE parent_id IS NULL
    FROM yourTable t WHERE parent_id IS NULL
    UNION ALL
        SELECT t2.marker || ':' || LPAD(t1.parent_id::text, 3, '0') || ':' ||
            LPAD(t1.id::text, 3, '0') AS marker,
            t2.buffer || '   ', t1.id, t1.parent_id, t2.buffer || t1.name
    FROM yourTable t1
    INNER JOIN cte t2
        ON t1.parent_id = t2.id
)

SELECT name FROM cte ORDER BY marker;


这里的基本思想是构建路径字符串,跟踪从每个节点到其根的完整路径(根由其
父\u id
NULL
的节点给出)。然后,我们只需在此路径上按进行一次排序即可生成所需的顺序。

下面是一个使用递归CTE的解决方案:

WITH RECURSIVE cte AS (
    SELECT LPAD(id::text, 3, '0') AS marker, '   ' AS buffer,
        id, parent_id, name::text
    FROM yourTable t WHERE parent_id IS NULL
    FROM yourTable t WHERE parent_id IS NULL
    UNION ALL
        SELECT t2.marker || ':' || LPAD(t1.parent_id::text, 3, '0') || ':' ||
            LPAD(t1.id::text, 3, '0') AS marker,
            t2.buffer || '   ', t1.id, t1.parent_id, t2.buffer || t1.name
    FROM yourTable t1
    INNER JOIN cte t2
        ON t1.parent_id = t2.id
)

SELECT name FROM cte ORDER BY marker;


这里的基本思想是构建路径字符串,跟踪从每个节点到其根的完整路径(根由其
父\u id
NULL
的节点给出)。然后,我们只需在此路径上按进行一次排序,即可生成所需的订单。

您还没有提供您已经提出的查询。但是-据我所知,您需要一个递归树结构

以及查询:

WITH RECURSIVE tree AS (
    SELECT
        rooms.id,
        rooms.parent_id,
        rooms.name
    FROM
        rooms
    WHERE
        parent_id IS NULL
    UNION ALL
    SELECT
        rooms.id,
        rooms.parent_id,
        rooms.name
    FROM
        tree
        JOIN rooms ON rooms.parent_id = tree.id
)
SELECT
    *
FROM
    tree;

您尚未提供您已经提出的查询。但是-据我所知,您需要一个递归树结构

以及查询:

WITH RECURSIVE tree AS (
    SELECT
        rooms.id,
        rooms.parent_id,
        rooms.name
    FROM
        rooms
    WHERE
        parent_id IS NULL
    UNION ALL
    SELECT
        rooms.id,
        rooms.parent_id,
        rooms.name
    FROM
        tree
        JOIN rooms ON rooms.parent_id = tree.id
)
SELECT
    *
FROM
    tree;

我尝试了此解决方案,并验证了此解决方案。非常感谢。@S.Kaio使用数组更简单一点:而且每个元素的路径都很容易使用。@Abelisto我测试了您的解决方案,非常感谢。感谢您的帮助:)我尝试了此解决方案,并验证了此解决方案。非常感谢。@S.Kaio使用数组更简单一点:而且每个元素的路径都很容易使用。@Abelisto我测试了您的解决方案,非常感谢。谢谢你的帮助:)很抱歉,如果我没有提供我已经提出的问题,但是我说了我不想要的结果。在这篇文章之前我做了你的查询,这个查询给了我我所说的坏结果。它返回如下层次结构:巴克莱大街1楼,2楼,3楼,1号大厅。。。但不是每个级别的所有层次结构。我非常感谢你,因为你试图帮助我。:)对不起,如果我没有提供我已经提出的问题,但是我说了我不想要的结果。在这篇文章之前我做了你的查询,这个查询给了我我所说的坏结果。它返回如下层次结构:巴克莱大街1楼,2楼,3楼,1号大厅。。。但不是每个级别的所有层次结构。我非常感谢你,因为你试图帮助我。:)
WITH RECURSIVE tree AS (
    SELECT
        rooms.id,
        rooms.parent_id,
        rooms.name
    FROM
        rooms
    WHERE
        parent_id IS NULL
    UNION ALL
    SELECT
        rooms.id,
        rooms.parent_id,
        rooms.name
    FROM
        tree
        JOIN rooms ON rooms.parent_id = tree.id
)
SELECT
    *
FROM
    tree;