如何在PostgreSQL中将单行年度值拆分为多行月度值?
在PostgreSQL中将年度支付记录拆分为月度记录
原表结构
| id | date | yearly_payment |
|---|---|---|
| 1 | 06/01/21 | $600 |
| 2 | 06/01/22 | $720 |
期望输出
| id | date | monthly_payment |
|---|---|---|
| 1 | 06/01/21 | $50 |
| 1 | 07/01/21 | $50 |
| 1 | ... | $50 |
| 1 | 05/01/22 | $50 |
| 2 | 06/01/22 | $60 |
| 2 | 07/01/22 | $60 |
| 2 | ... | $60 |
| 2 | 05/01/23 | $60 |
注:原示例中id=1的最后一条日期应为05/01/22(对应起始日期06/01/21),属于笔误,正确的12个月周期是从起始月开始连续顺延12个月。
解决方案(PostgreSQL)
使用PostgreSQL内置的generate_series函数生成连续月度序列,结合原表数据完成拆分:
SELECT t.id, -- 生成连续12个月度日期,按指定格式输出 TO_CHAR( (t.date::DATE + (interval '1 month' * s.offset)), 'MM/DD/YY' ) AS date, -- 计算月度支付额并还原$格式 '$' || ROUND((REPLACE(t.yearly_payment, '$', '')::NUMERIC / 12), 2)::TEXT AS monthly_payment FROM your_table_name t -- 关联0到11的偏移量,为每条年度记录生成12条月度记录 CROSS JOIN generate_series(0, 11) AS s(offset) ORDER BY t.id, date;
关键逻辑说明
- 月度日期生成:
generate_series(0,11)生成0到11的整数偏移量,对应12个月的间隔。- 将原表的
date字段转为DATE类型,叠加对应偏移量的月度间隔,再用TO_CHAR格式化为MM/DD/YY样式。
- 月度支付计算:
- 用
REPLACE移除金额字符串中的$,转为数值类型后除以12,通过ROUND保留两位小数,最后拼接$恢复格式。
- 用
- 记录拆分:
CROSS JOIN实现原表记录与12个偏移量的笛卡尔积,直接将单条年度记录扩展为12条月度记录。
适配调整提示
- 如果原表的
date字段已经是DATE类型,可去掉::DATE转换。 - 若无需保留两位小数,删除
ROUND函数即可。
内容的提问来源于stack exchange,提问作者kwarner
相关产品推荐
相关产品推荐

