SQL多行转多列求助:如何将同一REQUEST_ID的多行合并为一行
行转列解决方案:将多行REQUEST数据合并为单行
静态字段场景(固定FIELD_ID)
如果你的FIELD_ID对应的字段是固定的(比如示例中的2-5对应四个固定标签),可以用条件聚合实现行转列,这是最直接高效的方法:
SELECT r.REQUEST_ID, -- 提取Arrival Date相关字段 MAX(CASE WHEN d.FIELD_ID = 2 THEN d.FIELD_ID END) AS arrival_field_id, MAX(CASE WHEN d.FIELD_ID = 2 THEN f.LABEL_en END) AS arrival_label, MAX(CASE WHEN d.FIELD_ID = 2 THEN d.DATA END) AS arrival_date, -- 提取Departure Date相关字段 MAX(CASE WHEN d.FIELD_ID = 3 THEN d.FIELD_ID END) AS departure_field_id, MAX(CASE WHEN d.FIELD_ID = 3 THEN f.LABEL_en END) AS departure_label, MAX(CASE WHEN d.FIELD_ID = 3 THEN d.DATA END) AS departure_date, -- 提取Guest First Name相关字段 MAX(CASE WHEN d.FIELD_ID = 4 THEN d.FIELD_ID END) AS guest_first_field_id, MAX(CASE WHEN d.FIELD_ID = 4 THEN f.LABEL_en END) AS guest_first_label, MAX(CASE WHEN d.FIELD_ID = 4 THEN d.DATA END) AS guest_first_name, -- 提取Guest Last Name相关字段 MAX(CASE WHEN d.FIELD_ID = 5 THEN d.FIELD_ID END) AS guest_last_field_id, MAX(CASE WHEN d.FIELD_ID = 5 THEN f.LABEL_en END) AS guest_last_label, MAX(CASE WHEN d.FIELD_ID = 5 THEN d.DATA END) AS guest_last_name FROM TABLE_requests r INNER JOIN TABLE_fields_data d ON r.REQUEST_ID = d.REQUEST_ID INNER JOIN TABLE_fields f ON f.FIELD_ID = d.FIELD_ID GROUP BY r.REQUEST_ID;
关键逻辑说明
- GROUP BY 聚合:通过
GROUP BY r.REQUEST_ID将同一请求ID的所有行合并为一行 - CASE WHEN 筛选:针对每个
FIELD_ID,用CASE WHEN匹配对应的行,提取FIELD_ID、LABEL_en和DATA的值 - MAX函数取值:因为每个请求ID对应每个
FIELD_ID只有一条记录,MAX(或MIN)可以确保获取到唯一的非空值,避免聚合后出现NULL
查询结果示例
| REQUEST_ID | arrival_field_id | arrival_label | arrival_date | departure_field_id | departure_label | departure_date | guest_first_field_id | guest_first_label | guest_first_name | guest_last_field_id | guest_last_label | guest_last_name |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 47 | 2 | Arrival Date | 2018-08-11 | 3 | Departure Date | 2018-08-12 | 4 | Guest First Name | Daniel | 5 | Guest Last Name | Smith |
| 48 | 2 | Arrival Date | 2018-06-06 | 3 | Departure Date | 2018-05-08 | 4 | Guest First Name | Joseph | 5 | Guest Last Name | Client |
| 49 | 2 | Arrival Date | 2018-06-08 | 3 | Departure Date | 2018-06-09 | 4 | Guest First Name | Alberto | 5 | Guest Last Name | Customer |
动态字段场景(FIELD_ID不固定)
如果未来会新增FIELD_ID,静态的CASE WHEN需要手动修改,这时候可以用动态SQL生成查询语句,不同数据库的语法略有差异:
- MySQL:使用
CONCAT拼接SQL,再通过PREPARE和EXECUTE执行 - SQL Server:使用
STRING_AGG拼接字段,再通过EXEC执行 - PostgreSQL:使用
STRING_AGG拼接,再通过EXECUTE执行
以MySQL为例,动态SQL示例:
SET @sql = NULL; SELECT GROUP_CONCAT(DISTINCT CONCAT( 'MAX(CASE WHEN d.FIELD_ID = ', FIELD_ID, ' THEN d.FIELD_ID END) AS field_id_', FIELD_ID, ',', 'MAX(CASE WHEN d.FIELD_ID = ', FIELD_ID, ' THEN f.LABEL_en END) AS label_', FIELD_ID, ',', 'MAX(CASE WHEN d.FIELD_ID = ', FIELD_ID, ' THEN d.DATA END) AS data_', FIELD_ID ) ) INTO @sql FROM TABLE_fields; SET @sql = CONCAT('SELECT r.REQUEST_ID, ', @sql, ' FROM TABLE_requests r INNER JOIN TABLE_fields_data d ON r.REQUEST_ID = d.REQUEST_ID INNER JOIN TABLE_fields f ON f.FIELD_ID = d.FIELD_ID GROUP BY r.REQUEST_ID'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

