SQL技术问题:如何将同ID的两行数据合并为单行多列
实现同ID多行数据按评级提供商转列合并
要把同一ID下不同评级提供商的记录合并成一行,将提供商作为列名、对应评级作为列值,本质是**行转列(Pivot)**操作,不同数据库的实现方式略有不同,以下是常用数据库的解决方案:
示例表结构
假设你的表名为ratings,结构和数据如下:
CREATE TABLE ratings ( ID INT, Rating VARCHAR(10), `Rating Provider` VARCHAR(20) ); INSERT INTO ratings VALUES (5055, 'A+', 'Moodys'), (5055, 'Bb+', 'SNP');
注:你提供的期望结果中ID写成了5005,应该是笔误,实际合并后ID应为5055。
MySQL 实现(无原生Pivot函数)
用CASE WHEN配合聚合函数+GROUP BY实现:
SELECT ID, MAX(CASE WHEN `Rating Provider` = 'Moodys' THEN Rating END) AS Moodys, MAX(CASE WHEN `Rating Provider` = 'SNP' THEN Rating END) AS SNP FROM ratings GROUP BY ID;
原理:通过CASE WHEN匹配指定提供商,取出对应评级;用MAX(或MIN,因为每个ID对应每个提供商仅一条数据)聚合同一ID的结果,最终合并为一行。
SQL Server 实现(原生Pivot函数)
利用SQL Server自带的PIVOT语法,写法更简洁:
SELECT ID, Moodys, SNP FROM ratings PIVOT ( MAX(Rating) -- 聚合函数,这里用MAX是因为每个分组仅一条有效数据 FOR `Rating Provider` IN (Moodys, SNP) -- 指定要转成列的提供商名称 ) AS PivotResult;
PostgreSQL 实现
方式1:用CASE WHEN+GROUP BY(通用写法)
和MySQL逻辑一致:
SELECT ID, MAX(CASE WHEN "Rating Provider" = 'Moodys' THEN Rating END) AS Moodys, MAX(CASE WHEN "Rating Provider" = 'SNP' THEN Rating END) AS SNP FROM ratings GROUP BY ID;
方式2:用crosstab函数(更灵活)
需要先启用tablefunc扩展,适合提供商数量较多的场景:
-- 启用扩展(仅需执行一次) CREATE EXTENSION IF NOT EXISTS tablefunc; SELECT * FROM crosstab( 'SELECT ID, "Rating Provider", Rating FROM ratings ORDER BY 1', 'SELECT DISTINCT "Rating Provider" FROM ratings ORDER BY 1' ) AS ct_result (ID INT, Moodys TEXT, SNP TEXT);
内容的提问来源于stack exchange,提问作者quantnesto
相关产品推荐
相关产品推荐

