PostgreSQL中将多行列数据按时间合并为单行多列的实现方法
实现行转宽表的SQL方案
没问题,你需要把行格式的时序数据转成宽表,按t字段分组,把不同data_id对应的me/ma/mi/sd字段展开成带data_id前缀的列(比如1_me、1_ma)。这是SQL里很常见的透视操作,下面是通用的实现方法:
核心思路
通过条件聚合实现行转列:按t分组,对每个data_id的四个字段,用CASE WHEN筛选出对应记录的值,再用聚合函数(MAX/MIN均可,因为每个t+data_id组合唯一)提取该值,最终得到宽表结构。
具体SQL代码
假设你的表名为your_table,执行以下查询即可得到目标格式:
SELECT t, -- 提取data_id=1的四个字段 MAX(CASE WHEN data_id = 1 THEN me END) AS `1_me`, MAX(CASE WHEN data_id = 1 THEN ma END) AS `1_ma`, MAX(CASE WHEN data_id = 1 THEN mi END) AS `1_mi`, MAX(CASE WHEN data_id = 1 THEN sd END) AS `1_sd`, -- 提取data_id=2的四个字段 MAX(CASE WHEN data_id = 2 THEN me END) AS `2_me`, MAX(CASE WHEN data_id = 2 THEN ma END) AS `2_ma`, MAX(CASE WHEN data_id = 2 THEN mi END) AS `2_mi`, MAX(CASE WHEN data_id = 2 THEN sd END) AS `2_sd`, -- 提取data_id=3的四个字段 MAX(CASE WHEN data_id = 3 THEN me END) AS `3_me`, MAX(CASE WHEN data_id = 3 THEN ma END) AS `3_ma`, MAX(CASE WHEN data_id = 3 THEN mi END) AS `3_mi`, MAX(CASE WHEN data_id = 3 THEN sd END) AS `3_sd` FROM your_table GROUP BY t ORDER BY t;
查询结果示例
执行后会得到如下格式的结果:
| t | 1_me | 1_ma | 1_mi | 1_sd | 2_me | 2_ma | 2_mi | 2_sd | 3_me | 3_ma | 3_mi | 3_sd |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2010-04-14 00:00:00 | 12.6941 | 12.6941 | 12.6941 | 12.6941 | 12.3851 | 12.3851 | 12.3851 | 12.3851 | 11.6145 | 11.6145 | 11.6145 | 11.6145 |
| 2010-04-14 00:10:00 | 12.3890 | 12.3890 | 12.3890 | 12.3890 | 12.1836 | 12.1836 | 12.1836 | 12.1836 | 11.3887 | 11.3887 | 11.3887 | 11.3887 |
补充说明
如果你的数据库支持原生透视函数(比如MySQL 8.0+的PIVOT、PostgreSQL的crosstab),也可以用更简洁的语法,但上面的条件聚合方案兼容性最强,几乎所有SQL数据库都能运行。如果后续data_id增加,只需要对应新增CASE WHEN块即可。
内容的提问来源于stack exchange,提问作者iftekhar iftekhar
相关产品推荐
相关产品推荐

