You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL LTREE递归查询:如何仅对指定行执行递归?

解决LTREE混合查询需求:指定节点本身+特定分支全后代

可以通过带条件的递归CTE实现,无需拆分查询再UNION,逻辑更紧凑且避免重复行:

方案一:标记递归需求(通用型)

适合需要区分多个节点是否递归的场景,通过标记列控制递归范围:

WITH RECURSIVE node_query AS (
    -- 锚点:选中所有目标节点,标记是否需要展开后代
    SELECT 
        path,
        CASE 
            WHEN path IN ('Top.Science'::ltree, 'Top.Collections'::ltree) THEN false
            WHEN path = 'Top.Collections.Pictures.Astronomy'::ltree THEN true
        END AS need_recurse
    FROM nodes
    WHERE path IN (
        'Top.Science'::ltree, 
        'Top.Collections'::ltree, 
        'Top.Collections.Pictures.Astronomy'::ltree
    )

    UNION ALL

    -- 递归分支:仅处理标记为需要递归的节点,获取其所有后代
    SELECT 
        n.path,
        false AS need_recurse  -- 后代无需再递归,防止循环或重复
    FROM nodes n
    JOIN node_query p 
        ON p.path <@ n.path  -- 匹配父节点的所有后代
        AND p.path != n.path -- 排除父节点本身(锚点已包含)
    WHERE p.need_recurse = true
)
SELECT DISTINCT path FROM node_query;

方案二:直接限定递归触发条件(简化版)

如果只有一个分支需要递归,可以直接在递归连接条件里指定目标节点,省去标记列:

WITH RECURSIVE node_query AS (
    -- 锚点:选中所有目标节点
    SELECT path FROM nodes
    WHERE path IN (
        'Top.Science'::ltree, 
        'Top.Collections'::ltree, 
        'Top.Collections.Pictures.Astronomy'::ltree
    )

    UNION ALL

    -- 仅递归Astronomy分支的后代
    SELECT n.path
    FROM nodes n
    JOIN node_query p 
        ON p.path = 'Top.Collections.Pictures.Astronomy'::ltree -- 仅针对该节点递归
        AND p.path <@ n.path 
        AND p.path != n.path
)
SELECT DISTINCT path FROM node_query;

为什么这个方案能解决重复问题?

之前用<@关联全量递归时,Top.Collections会匹配到它的所有后代(包括Astronomy分支),而Astronomy自身的递归又会拉一次后代,导致重复。现在通过限制仅Astronomy节点触发递归,Top.Science和Top.Collections仅保留自身,不会展开子节点,从根源避免了重复。

内容的提问来源于stack exchange,提问作者sudoExclamationExclamation

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 05:32:43