You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL 9.4.26中如何生成日期序列并保留首尾日期

问题描述

使用PostgreSQL 9.4.26,现有表格数据如下:

KeyStartEnd
ABC12324/01/201223/01/2013

需要将该跨年度的日期范围按月拆分,得到每个月对应的日期区间:第一个月保留原起始日期(24/01/2012),最后一个月保留原结束日期(23/01/2013),中间月份为完整自然月。

原查询生成的第一条记录起始日期为1/01/2012,不符合预期,需修正。

原查询问题分析

原查询中generate_series的起始值使用date_trunc('month', start_date),直接取原起始日期所在月份的第一天,导致第一个月的起始日期丢失了原数据的具体日份。

修正后的查询语句
WITH date_ranges AS (
    SELECT
        "Key",
        TO_DATE("Start", 'DD/MM/YYYY') AS start_date,
        TO_DATE("End", 'DD/MM/YYYY') AS end_date
    FROM tabl
)
SELECT
    "Key",
    TO_CHAR(
        CASE
            WHEN month_start = date_trunc('month', start_date) THEN start_date
            ELSE month_start
        END,
        'DD/MM/YYYY'
    ) AS "Start",
    TO_CHAR(
        LEAST(
            (month_start + INTERVAL '1 month') - INTERVAL '1 day',
            end_date
        ),
        'DD/MM/YYYY'
    ) AS "End"
FROM date_ranges
CROSS JOIN LATERAL generate_series(
    date_trunc('month', start_date),
    date_trunc('month', end_date),
    INTERVAL '1 month'
) AS month_start(month_start);
关键修改说明
  1. 保留原Key字段:在CTEdate_ranges中加入"Key",确保输出结果包含该字段。
  2. 修正起始日期逻辑:通过CASE判断生成的月份起始是否为原起始日期所在月份的月初,若是则使用原start_date,否则使用当月第一天,保证第一个月保留原起始日。
  3. 调整序列结束值:将generate_series的结束值改为date_trunc('month', end_date),确保序列覆盖到结束日期所在月份的月初,再通过LEAST函数处理最后一个月的结束日期为原end_date。
验证结果

执行修正后的语句,将得到预期的拆分结果:

KeyStartEnd
ABC12324/01/201231/01/2012
ABC1231/02/201229/02/2012
ABC1231/03/201231/03/2012
ABC1231/04/201230/04/2012
ABC1231/05/201231/05/2012
ABC1231/06/201230/06/2012
ABC1231/07/201231/07/2012
ABC1231/08/201231/08/2012
ABC1231/09/201230/09/2012
ABC1231/10/201231/10/2012
ABC1231/11/201230/11/2012
ABC1231/12/201231/12/2012
ABC1231/01/201323/01/2013

内容的提问来源于stack exchange,提问作者vin.1056465

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 04:03:13