SQL多行转多列实现同组属性合并到同一行的操作方法
实现方案(最优高性能版)
大数据量下推荐使用窗口函数+条件聚合的实现方式,仅需一次全表扫描即可完成转换,相比原生PIVOT语法兼容性更强、执行效率更高,避免多轮IO开销。
具体SQL代码
假设你的原表名为sku_sales_rank,代码如下:
SELECT Sku_Code, Channel, MAX(CASE WHEN rn = 1 THEN Category END) AS Category, MAX(CASE WHEN rn = 2 THEN Category END) AS Category_1, MAX(CASE WHEN rn = 1 THEN Website END) AS Website, MAX(CASE WHEN rn = 2 THEN Website END) AS Website_1, Date FROM ( SELECT *, -- 按三个分组字段分区,给组内每行分配唯一序号 ROW_NUMBER() OVER (PARTITION BY Sku_Code, Channel, Date ORDER BY Rank) AS rn FROM sku_sales_rank ) t GROUP BY Sku_Code, Channel, Date;
代码说明
- 内层子查询用
ROW_NUMBER()窗口函数,将Sku_Code、Channel、Date三个字段值相同的行划为同一分组,组内按Rank排序后生成从1开始的连续行号 - 外层用条件聚合:同一行号对应唯一的Category和Website值,用MAX/MIN聚合函数取出对应值,组内不存在对应行号的字段自动返回空值,完全匹配你需要的输出效果
- 如果你的业务场景中同一个分组下最多有N条重复行,只需要对应加
CASE WHEN rn = N THEN xxx END的聚合字段即可
性能优化建议
如果表数据量达到千万级以上,提前给Sku_Code, Channel, Date三个字段建立联合索引,窗口函数可直接利用索引的有序性生成分组行号,避免额外的内存/磁盘排序开销,执行速度可提升数倍。
PIVOT语法补充说明
如果你使用的数据库支持原生PIVOT语法(比如Oracle、SQL Server、Spark SQL),也可以用PIVOT实现,但本质底层逻辑和上述条件聚合一致,性能差异不大,上述写法兼容性更强,可在MySQL、PostgreSQL等所有支持窗口函数的数据库中运行。
内容的提问来源于stack exchange,提问作者Sluna
相关产品推荐
相关产品推荐

