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

如何在Oracle中基于节假日表通过CTE生成日历表

没问题,这需求用递归CTE就能轻松搞定——先生成覆盖节假日表最小开始日期到最大结束日期的完整日历,再关联节假日表匹配每天对应的假期名称。我给你写个完整的实现方案,带详细解释:

实现方案

完整SQL代码

WITH DateRange AS (
    -- 递归起始:取节假日表的最早开始日期
    SELECT MIN(FromDate) AS CalendarDate
    FROM holidays
    UNION ALL
    -- 递归生成后续日期,直到达到最晚结束日期
    SELECT DATEADD(day, 1, CalendarDate)
    FROM DateRange
    WHERE CalendarDate < (SELECT MAX(ToDate) FROM holidays)
)
-- 关联日历和节假日表,匹配每日的假期名称
SELECT 
    dr.CalendarDate AS Date,
    h.Description AS HolidayName
FROM DateRange dr
LEFT JOIN holidays h 
    ON dr.CalendarDate BETWEEN h.FromDate AND h.ToDate
-- 若要保留非节假日日期(显示NULL),可删除此WHERE子句
WHERE h.Description IS NOT NULL
ORDER BY dr.CalendarDate;

代码细节解释

  • 递归CTE DateRange:
    • 第一部分(UNION ALL之前):先拿到holidays表中最早的FromDate,作为日历的起始点。
    • 第二部分:每次在前一天的基础上加1天,循环生成新日期,直到日期超过holidays表中最晚的ToDate为止,这样就得到了完整的日期范围。
  • 关联匹配:用生成的日历日期和holidays表做左连接,通过BETWEEN判断日期是否落在某个假期的起止范围内,从而拿到对应的假期名称。
  • 过滤与排序:如果只需要显示有假期的日期,就保留WHERE h.Description IS NOT NULL;如果要包含所有日期(非假期显示NULL),直接删掉这个条件就行。最后按日期排序让结果更规整。

适配不同数据库的小提示

  • 如果用的是MySQL,把DATEADD(day, 1, CalendarDate)换成DATE_ADD(CalendarDate, INTERVAL 1 DAY);
  • 如果是PostgreSQL,换成CalendarDate + INTERVAL '1 day';
  • 如果存在假期日期范围重叠的情况,这个查询会返回重复的日期记录(每个重叠假期各一条),你可以根据业务需求调整,比如加个优先级字段筛选,或者用字符串函数合并名称。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:57:01