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

如何拼接同表不同行单元格?SQL语句问题求助

解决Oracle中分类行TEXT拼接及重复行问题

首先,我先梳理下你的核心需求:

  • 基于BLTGS1-6的分类逻辑,将BLTUGP为数字(1/2)的行的TEXT,拼接至同分类下上方第一个BLTUGP非数字/空的行的TEXT内容
  • 必须保留所有BLTUGP为空/NULL的行,且原表不能修改

你现有语句的问题分析

你当前的CTE+UNION方案出现重复行,主要有几个原因:

  1. 第二个CTE的RIGHT JOIN条件里,u.bltgs6=u.bltgs6是无效条件(恒成立),这会导致每个u行匹配所有符合条件的h行,直接产生重复
  2. 两个CTE的分组/TEXT生成逻辑不一致:tbl_wougp用了LISTAGG聚合文本,而tbl_wugp直接取单条bltxt,导致同一分组的行可能在两个CTE中都被输出,UNION后出现重复
  3. RIGHT JOIN会保留所有u行,即使找不到对应的h行,这时候拼接会出现NULL值,不符合你的预期

优化后的解决方案

我们可以利用Oracle的窗口函数LAST_VALUE来精准定位每个数字BLTUGP行对应的父行文本,避免JOIN带来的重复问题,同时统一TEXT的生成逻辑:

WITH base_data AS (
    -- 先统一处理所有行的TEXT,和你原逻辑一致用LISTAGG聚合
    SELECT 
        bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, 
        bltugp,
        regexp_replace(regexp_replace(LISTAGG(bltxt,' ') WITHIN GROUP (ORDER BY blttkz),'\s+',' '),'¯+','') AS original_text
    FROM atdata.bip105 
    WHERE bltspriso = 'DEAT'
    GROUP BY bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz, bltugp
),
with_parent_text AS (
    -- 用窗口函数找到同分类下,当前行之前最近的非数字BLTUGP行的TEXT
    SELECT 
        *,
        LAST_VALUE(CASE WHEN NOT REGEXP_LIKE(bltugp, '^[0-9]+$') THEN original_text END IGNORE NULLS) 
            OVER (PARTITION BY bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6 
                  ORDER BY blttkz, bltugp 
                  ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS parent_text
    FROM base_data
)
-- 生成最终结果:数字BLTUGP行拼接父文本,其他行保留原文本,同时去重
SELECT 
    bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6,
    bltugp,
    CASE 
        WHEN REGEXP_LIKE(bltugp, '^[0-9]+$') AND parent_text IS NOT NULL 
            THEN TRIM(parent_text || ' ' || original_text)
        ELSE original_text
    END AS Text
FROM with_parent_text
GROUP BY bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, bltugp, original_text, parent_text
ORDER BY bltgs1, bltgs2, bltgs3, bltgs4, bltgs5, bltgs6, blttkz, bltugp;

方案说明

  1. base_data CTE:统一对所有分组执行LISTAGG文本聚合,确保所有行的TEXT生成逻辑一致,避免后续重复
  2. with_parent_text CTE:
    • PARTITION BY bltgs1-6确保只在同一分类内查找父行
    • LAST_VALUE(... IGNORE NULLS)会跳过BLTUGP为数字的行,精准定位当前行之前最近的非数字BLTUGP行的TEXT
    • ORDER BY blttkz, bltugp保证排序和你原逻辑一致,确保父行是"上方"的行
  3. 最终SELECT:
    • 对BLTUGP为数字的行,拼接父文本和当前文本(用TRIM避免多余空格)
    • 对其他行(空/非数字BLTUGP)直接保留原文本
    • 最后用GROUP BY去重,避免窗口函数或分组逻辑可能产生的重复行

这样就能完美实现你的需求,同时解决重复行的问题。

内容的提问来源于stack exchange,提问作者F.Gradl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:51:24