表结构问题:如何通过Pivot/Unpivot实现数据转换查询
解决你的表结构转换问题:用Pivot实现Draw分组聚合
看起来你是想把这种"键值对"格式的表,转换成每个Draw组一行的结构化表对吧?你的思路方向是对的,不过不需要Unpivot(因为原表已经是Unpivot后的长格式了),咱们通过分组+Pivot就能搞定,下面给你一步步拆解方案:
先明确目标结构
以你提供的ID=1的数据为例,最终我们要得到的表应该是这样的:
| ID | draw_group | Amount | DrawDate | Fee |
|---|---|---|---|---|
| 1 | Draw1 | 1500 | 4/15/16 | 100 |
| 1 | Draw2 | 2000 | 3/14/17 | 100 |
分步实现方案
第一步:为每条记录标记分组和属性类型
首先得把原表field字段里的信息拆出来:比如Draw1Date属于Draw1分组,对应属性是日期;Draw1Fee属于Draw1分组,对应属性是费用;Draw1本身属于Draw1分组,对应属性是金额。
以SQL Server为例,我们先写一个CTE来整理数据:
WITH grouped_data AS ( SELECT ID, -- 标记这条记录对应的属性类型:金额/日期/费用 CASE WHEN field LIKE 'Draw%Date' THEN 'DrawDate' WHEN field LIKE 'Draw%Fee' THEN 'Fee' ELSE 'Amount' END AS attribute, -- 统一值的类型(value是数值,date是日期,转成字符串保证Pivot类型一致) CASE WHEN field LIKE 'Draw%Date' THEN CONVERT(VARCHAR(10), date, 101) ELSE CONVERT(VARCHAR(20), value) END AS attr_value, -- 提取所属的Draw分组(比如Draw1、Draw2) CASE WHEN field LIKE '%Date' OR field LIKE '%Fee' THEN LEFT(field, LEN(field)-4) ELSE field END AS draw_group FROM your_table )
第二步:用Pivot将属性转成列
有了整理好的分组数据,就可以用Pivot把每个分组对应的三个属性转成列了:
SELECT ID, draw_group, Amount, DrawDate, Fee FROM grouped_data PIVOT ( -- 用MAX聚合,因为每个分组+属性只会有一个值 MAX(attr_value) -- 要转成列的属性字段 FOR attribute IN (Amount, DrawDate, Fee) ) AS pivot_result ORDER BY ID, draw_group;
如果你用MySQL(无原生Pivot)
MySQL不支持直接的Pivot关键字,用条件聚合就能达到同样效果,写法更通用:
WITH grouped_data AS ( SELECT ID, CASE WHEN field LIKE '%Date' THEN LEFT(field, LOCATE('Date', field)-1) WHEN field LIKE '%Fee' THEN LEFT(field, LOCATE('Fee', field)-1) ELSE field END AS draw_group, CASE WHEN field NOT LIKE '%Date' AND field NOT LIKE '%Fee' THEN value END AS Amount, CASE WHEN field LIKE '%Date' THEN date END AS DrawDate, CASE WHEN field LIKE '%Fee' THEN value END AS Fee FROM your_table ) SELECT ID, draw_group, MAX(Amount) AS Amount, MAX(DrawDate) AS DrawDate, MAX(Fee) AS Fee FROM grouped_data GROUP BY ID, draw_group ORDER BY ID, draw_group;
关键说明
- 为什么不用Unpivot?因为你的原表已经是"长格式"(每条记录是一个键值对),Unpivot是用来把宽格式转成长格式的,咱们现在是要把长格式转成更结构化的宽格式,所以用Pivot就够了。
- 字符串处理函数需要根据你用的数据库调整,比如Oracle用
SUBSTR+INSTR,核心思路都是一样的:把DrawN、DrawNDate、DrawNFee归到同一个DrawN分组里。
内容的提问来源于stack exchange,提问作者Kharvok
相关产品推荐
相关产品推荐

