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

PL/SQL实现Unpivot列转行:单ID仅一行问题求解

解决宽表转多行窄表的Union/Unpivot实现问题

看起来你是要把这种“宽格式”的表转换成“长格式”,但之前用Union或Unpivot时没得到预期的多行结果,大概率是用法上的小问题,我给你两种靠谱的解决方法:

方法一:用UNION ALL(别用UNION!)

你之前可能踩了UNION的坑——它会自动去重,如果同一ID的几行数据完全相同,就会被合并成一行。换成UNION ALL就能保留所有行,写法非常直接:

SELECT ID, A_1 AS A, B_1 AS B FROM your_table
UNION ALL
SELECT ID, A_2 AS A, B_2 AS B FROM your_table
UNION ALL
SELECT ID, A_3 AS A, B_3 AS B FROM your_table
ORDER BY ID;

这个逻辑就是把每组A_n/B_n分别作为独立的查询结果,再把三个结果集拼接起来,UNION ALL会原封不动保留所有行,不会做去重操作。

方法二:用Cross Apply/Lateral Join(更灵活的行转列方式)

如果你的数据库支持CROSS APPLY(比如SQL Server)或者LATERAL JOIN(比如PostgreSQL、MySQL 8.0+),这种方式比传统Unpivot更直观,特别适合处理成对的列:

-- SQL Server 写法
SELECT t.ID, u.A, u.B
FROM your_table t
CROSS APPLY (
    VALUES
        (A_1, B_1),
        (A_2, B_2),
        (A_3, B_3)
) u(A, B)
ORDER BY t.ID;

-- PostgreSQL/MySQL 8.0+ 写法
SELECT t.ID, u.A, u.B
FROM your_table t
LATERAL (
    VALUES
        (A_1, B_1),
        (A_2, B_2),
        (A_3, B_3)
) u(A, B)
ORDER BY t.ID;

这种方式相当于给每一行原始数据,生成三行对应A_1/B_1、A_2/B_2、A_3/B_3的记录,完美匹配你的需求。

如果你一定要用传统UNPIVOT

传统Unpivot默认只能处理单个列的拆分,所以需要分别拆A列和B列,再通过ID和序号关联起来:

WITH A_data AS (
    SELECT 
        ID,
        A_val AS A,
        -- 提取序号数字,用来关联对应的B列
        CAST(REPLACE(seq_col, 'A_', '') AS INT) AS seq
    FROM your_table
    UNPIVOT (
        A_val FOR seq_col IN (A_1, A_2, A_3)
    ) up
),
B_data AS (
    SELECT 
        ID,
        B_val AS B,
        CAST(REPLACE(seq_col, 'B_', '') AS INT) AS seq
    FROM your_table
    UNPIVOT (
        B_val FOR seq_col IN (B_1, B_2, B_3)
    ) up
)
SELECT a.ID, a.A, b.B
FROM A_data a
JOIN B_data b ON a.ID = b.ID AND a.seq = b.seq
ORDER BY a.ID;

这个方法的核心是把A和B列分别Unpivot后,通过提取的序号(1、2、3)来确保每一组A_n和B_n对应上,避免数据错位。

总结一下,你之前的问题大概率是用了UNION(去重导致合并行),或者Unpivot时没处理好成对列的关联,试试上面的方法就能解决啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 22:17:40