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

如何简化日历表中假期关联后续工作日的SQL查询?

优化假期关联首个工作日的SQL查询

问题描述

我有一个日历表mts_calendar,每条日期记录带有标识字段mts,若为假期则标识为'H'。我希望创建一个派生表,将每个假期日期关联至紧随其后的首个工作日。当前使用的SQL查询虽能实现需求,但执行成本较高,是否有简化该代码的方法?

现有SQL:

select a.data_oss hd, min(b.data_oss) next_wd
from mts_calendar a 
join mts_calendar b on b.mts != 'H' and b.data_oss > a.data_oss and b.data_oss < a.data_oss +10
where a.mts = 'H'
group by a.data_oss

优化方案

原查询通过自连接加分组聚合实现需求,但每个假期日期都要扫描后续10天的数据,执行效率低下。可以利用窗口函数优化,避免冗余的自连接和分组操作:

方法1:支持IGNORE NULLS的数据库(如PostgreSQL 11+、Oracle、SQL Server 2022+)

直接跳过假期的NULL值,获取后续首个工作日,仅需一次全表扫描:

WITH calendar_with_next_wd AS (
    SELECT 
        data_oss,
        mts,
        LAST_VALUE(CASE WHEN mts != 'H' THEN data_oss END) OVER (
            ORDER BY data_oss 
            ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
            IGNORE NULLS
        ) AS next_wd
    FROM mts_calendar
)
SELECT 
    data_oss AS hd,
    next_wd
FROM calendar_with_next_wd
WHERE mts = 'H'

方法2:不支持IGNORE NULLS的数据库(如MySQL 8.0)

通过反向遍历标记最近工作日,同样实现高效查询:

WITH reversed_calendar AS (
    SELECT 
        data_oss,
        mts,
        MAX(CASE WHEN mts != 'H' THEN data_oss END) OVER (ORDER BY data_oss DESC) AS next_wd
    FROM mts_calendar
)
SELECT 
    data_oss AS hd,
    next_wd
FROM reversed_calendar
WHERE mts = 'H'
ORDER BY data_oss

优化说明

原查询的自连接逻辑时间复杂度为O(n²),窗口函数方案仅需一次线性扫描(O(n)),数据量越大效率提升越明显。另外,给data_oss字段建立索引,能进一步加快窗口函数的排序计算速度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 16:05:03