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

Oracle SQL:根据表中日期参数生成每日数据的技术需求

解决仓库区间数据展开为每日记录的问题

嘿,我来帮你搞定这个日期展开的需求!你需要把仓库的区间数据拆成每日记录,还要处理两种end_date的情况,我给你分主流数据库写了具体的实现方案,你可以根据自己用的数据库来选:

通用递归CTE方案(适用于SQL Server、MySQL 8.0+、PostgreSQL等)

这种方法用递归公共表表达式(CTE)生成日期序列,兼容性比较好:

-- 注意:MySQL需要在WITH后加RECURSIVE关键字
WITH RECURSIVE warehouse_adjusted AS (
    -- 先统一处理end_date:NULL时替换为start_date+3650天
    SELECT 
        warehouse,
        start_date,
        CASE 
            WHEN end_date IS NULL THEN DATE_ADD(start_date, INTERVAL 3650 DAY) -- MySQL写法
            -- 其他数据库可以改成:start_date + INTERVAL '3650 days'
            ELSE end_date
        END AS end_date,
        distance
    FROM warehouse
),
date_series AS (
    -- 初始行:每条记录的start_date
    SELECT 
        warehouse,
        start_date AS run_date,
        end_date,
        distance
    FROM warehouse_adjusted
    UNION ALL
    -- 递归生成后续日期,直到run_date达到end_date
    SELECT 
        warehouse,
        DATE_ADD(run_date, INTERVAL 1 DAY), -- MySQL写法
        -- 其他数据库改成:run_date + INTERVAL '1 day'
        end_date,
        distance
    FROM date_series
    WHERE run_date < end_date
)
-- 输出最终需要的字段
SELECT warehouse, run_date, distance
FROM date_series
ORDER BY warehouse, run_date;

代码说明:

  • warehouse_adjusted CTE:先把NULL的end_date转换成start_date+3650天,让后续递归逻辑不用再判断空值,简化代码。
  • date_series递归CTE:从每条记录的起始日期开始,每天加1天,直到日期不小于end_date为止,这样会自动包含起始和结束当天的记录。

PostgreSQL专属高效方案(用generate_series函数)

PostgreSQL自带的generate_series可以直接生成日期序列,比递归更简洁高效:

SELECT 
    w.warehouse,
    generate_series(
        w.start_date,
        -- 处理end_date的逻辑:空值则取start_date+3650天
        CASE WHEN w.end_date IS NULL THEN w.start_date + INTERVAL '3650 days' ELSE w.end_date END,
        INTERVAL '1 day'
    )::DATE AS run_date,
    w.distance
FROM warehouse w
ORDER BY w.warehouse, run_date;

Oracle专属方案(用CONNECT BY LEVEL)

如果用Oracle,你可以用层级查询来生成日期序列:

SELECT 
    warehouse,
    start_date + (LEVEL - 1) AS run_date,
    distance
FROM warehouse
CONNECT BY 
    -- 计算需要生成的天数:非空end_date则取区间天数,空则取3651天(包含起始日)
    LEVEL <= CASE 
                WHEN end_date IS NULL THEN 3651
                ELSE end_date - start_date + 1
            END
    -- 确保同一仓库的记录层级关联,避免跨仓库循环
    AND PRIOR warehouse = warehouse
    AND PRIOR SYS_GUID() IS NOT NULL
ORDER BY warehouse, run_date;

小提示:

之前用LEVEL没成功可能是没处理好空值的天数计算,或者没加PRIOR SYS_GUID()来避免循环关联,上面的代码已经帮你补全了这些细节。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 13:32:33