postgresql 递归CTE中的EXISTS条件

62o28rlo  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(149)

我尝试使用“EXISTS condition in RECURSIVE CTE”来停止递归,但是我得到了SQL错误[42 P19]。PostgreSQL version 13.2。有没有办法绕过这个限制?
下面的SQL查询创建了一个具有节点-父节点关系的表。我需要构建从任何基节点到任何嵌套节点的相对路径。例如。给定输入参数base_id(1)和rel_id(4),结果应该是“1/2/4”。
如果从查询中删除部分EXISTS,结果将是正确的,但如果有100多条深度记录,这将严重影响性能。

DROP TABLE IF EXISTS nodes;

CREATE TABLE nodes (
    id INT4
    , parent_id INT4
);

INSERT INTO nodes (
    id, parent_id
) VALUES (
    1, NULL
), (
    2, 1
), (
    3, 1
), (
    4, 2
), (
    5, 4
);

-- get rel path by base id 1 to rel id 4
WITH RECURSIVE r AS (
    SELECT n.id, n.parent_id, CAST(n.id AS VARCHAR) rel_path
    FROM nodes n
    WHERE n.id = 1 -- base
    UNION ALL 
    SELECT n.id, n.parent_id, CONCAT(rel_path, ' / ', n.id) rel_path
    FROM r
    JOIN nodes n ON n.parent_id = r.id
    WHERE NOT EXISTS (
        SELECT *
        FROM r r_sub
        WHERE r_sub.id = 4 -- rel
    )
)
SELECT *
FROM r
WHERE id = 4; -- rel

字符串
sandbox rel https://extendsclass.com/postgresql/1a1bc61

tkclm6bt

tkclm6bt1#

你已经在你的查询中有r,过滤器可以简化为!=。它不会停止替代路径,但你可以在最外面的选择中额外过滤。

WITH RECURSIVE r AS (
    SELECT n.id, n.parent_id, n.id::text rel_path -- here you need to initiate rel_path
    FROM nodes n
    WHERE n.id = 1 -- base
    UNION ALL 
    SELECT n.id, n.parent_id, CONCAT(rel_path, ' / ', n.id) rel_path
    FROM r
    JOIN nodes n ON n.parent_id = r.id
    WHERE r.id != 4
)
SELECT rel_path
FROM r
where r.id = 4

字符串
结果:1 / 2 / 4

相关问题