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

PostgreSQL中CTE递归查询结果的压缩转换实现方法咨询

递归CTE结果转换为压缩表的实现方案

要将递归CTE生成的层级表转换为包含id、parent_info、lit的目标表,核心是生成parent_info字段——即当前节点所有父节点的相关信息拼接串。最高效的方式是在递归CTE内部直接构建parent_info,后续只需筛选目标字段即可;也可以在CTE外部通过自连接+聚合函数实现。以下是具体实现:

方案1:递归过程中构建parent_info(推荐)

这种方式不需要额外的连接操作,性能更优。在递归的每一层,将父节点的parent_info与父节点的标识信息(比如from+prod)拼接,最终每个节点都会携带完整的父路径信息。

PostgreSQL/SQL Server 示例

WITH recursive_data AS (
    -- 初始查询:选取根节点(无父节点),parent_info初始为空
    SELECT 
        id, 
        "from", 
        prod, 
        parent_id, 
        lit, 
        tip,
        CAST('' AS VARCHAR(1000)) AS parent_info
    FROM your_table
    WHERE parent_id IS NULL

    UNION ALL

    -- 递归部分:拼接父节点的parent_info与父节点的标识
    SELECT 
        t.id, 
        t."from", 
        t.prod, 
        t.parent_id, 
        t.lit, 
        t.tip,
        CONCAT(
            rd.parent_info, 
            CASE WHEN rd.parent_info <> '' THEN ' > ' ELSE '' END, 
            CONCAT(rd."from", ':', rd.prod)
        ) AS parent_info
    FROM your_table t
    JOIN recursive_data rd ON t.parent_id = rd.id
)
-- 直接筛选目标字段
SELECT id, parent_info, lit
FROM recursive_data;

MySQL 示例

MySQL使用CONCAT_WS处理拼接更简洁,自动处理分隔符的空值情况:

WITH RECURSIVE recursive_data AS (
    SELECT 
        id, 
        `from`, 
        prod, 
        parent_id, 
        lit, 
        tip,
        '' AS parent_info
    FROM your_table
    WHERE parent_id IS NULL

    UNION ALL

    SELECT 
        t.id, 
        t.`from`, 
        t.prod, 
        t.parent_id, 
        t.lit, 
        t.tip,
        CONCAT_WS(' > ', rd.parent_info, CONCAT(rd.`from`, ':', rd.prod)) AS parent_info
    FROM your_table t
    JOIN recursive_data rd ON t.parent_id = rd.id
)
SELECT id, parent_info, lit
FROM recursive_data;

方案2:CTE外部通过自连接+聚合生成parent_info

如果无法在递归内部修改,可以通过自连接递归结果集,用字符串聚合函数拼接父节点信息:

PostgreSQL/SQL Server 示例

WITH recursive_data AS (
    -- 你的原有递归查询,需包含层级字段level
    SELECT id, "from", prod, parent_id, lit, tip, 1 AS level
    FROM your_table
    WHERE parent_id IS NULL
    UNION ALL
    SELECT t.id, t."from", t.prod, t.parent_id, t.lit, t.tip, rd.level + 1
    FROM your_table t
    JOIN recursive_data rd ON t.parent_id = rd.id
)
SELECT 
    rd_child.id,
    -- 按层级顺序拼接当前节点的所有父节点信息
    STRING_AGG(CONCAT(rd_parent."from", ':', rd_parent.prod), ' > ') OVER (
        PARTITION BY rd_child.id 
        ORDER BY rd_parent.level 
        ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
    ) AS parent_info,
    rd_child.lit
FROM recursive_data rd_child
LEFT JOIN recursive_data rd_parent ON rd_child.id IN (SELECT id FROM recursive_data WHERE parent_id = rd_parent.id)
GROUP BY rd_child.id, rd_child.lit;

自定义parent_info格式

如果parent_info需要包含其他字段(比如父节点ID),只需修改拼接逻辑即可。例如要包含父节点ID:

-- 以PostgreSQL为例,修改递归部分的拼接
CONCAT(
    rd.parent_info, 
    CASE WHEN rd.parent_info <> '' THEN ' > ' ELSE '' END, 
    CONCAT('ID:', rd.id, ' (', rd."from", ':', rd.prod, ')')
) AS parent_info

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 20:40:55