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

如何使用SQL按起止日期范围将单条记录拆分为多行

日期范围拆分实现方案

以下实现默认你的原始表名为t_range,可根据实际业务的表名替换。

核心逻辑为:生成覆盖你所有数据时间范围的连续日期序列,将原表与日期序列关联,关联条件为连续日期落在原表的start_date和end_date区间内。

PostgreSQL 版本

可直接调用内置的generate_series函数生成连续日期:

SELECT 
    t.id,
    t.start_date,
    t.end_date,
    t.amount,
    s.operation_date
FROM t_range t
CROSS JOIN generate_series(t.start_date, t.end_date, '1 day'::interval) AS s(operation_date);

MySQL 8.0+ 版本

用递归CTE生成连续日期序列后关联:

WITH RECURSIVE date_series AS (
    -- 取最小起始日期作为序列起点
    SELECT MIN(start_date) AS dt FROM t_range
    UNION ALL
    SELECT dt + INTERVAL 1 DAY FROM date_series 
    WHERE dt < (SELECT MAX(end_date) FROM t_range)
)
SELECT 
    t.id,
    t.start_date,
    t.end_date,
    t.amount,
    d.dt AS operation_date
FROM t_range t
JOIN date_series d ON d.dt BETWEEN t.start_date AND t.end_date;

如果是低版本MySQL不支持CTE,可提前维护一张日期维度表,直接用维度表和原表按上述关联条件关联即可。

Hive/Spark SQL 版本

用侧视图 + 序列生成函数实现:

SELECT 
    t.id,
    t.start_date,
    t.end_date,
    t.amount,
    date_add(t.start_date, pos) AS operation_date
FROM t_range t
LATERAL VIEW posexplode(split(space(datediff(end_date, start_date)), ' ')) pe AS pos, val;

-- 高版本Spark SQL也可以直接用sequence函数简化写法
-- SELECT 
--     t.*,
--     single_date AS operation_date 
-- FROM t_range t 
-- LATERAL VIEW explode(sequence(to_date(start_date), to_date(end_date), interval 1 day)) tmp AS single_date

Oracle 版本

用CONNECT BY递归实现:

SELECT 
    t.id,
    t.start_date,
    t.end_date,
    t.amount,
    t.start_date + (LEVEL - 1) AS operation_date
FROM t_range t
CONNECT BY LEVEL <= (t.end_date - t.start_date + 1)
AND PRIOR t.id = t.id
AND PRIOR SYS_GUID() IS NOT NULL;

内容的提问来源于stack exchange,提问作者user5740635

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 04:15:05