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

基于日期合并重叠事件并拆分非重叠时段的SQL解决方案求助

解决方案:按重叠时段合并同起始周日的事件

以下分别提供Spark SQL和SQL Server的实现代码,满足仅同起始周日的重叠事件合并、非重叠时段单独成行的需求。

Spark SQL 实现

假设输入表Input结构为:Event STRING, Start_Date DATE, End_Date DATE,代码如下:

WITH EventTimePoints AS (
    -- 提取同起始周日下所有事件的开始时间,以及结束时间+1(用于生成连续区间)
    SELECT 
        Start_Date AS Base_Start,
        Event,
        Start_Date AS TimePoint
    FROM Input
    UNION ALL
    SELECT 
        Start_Date AS Base_Start,
        Event,
        DATE_ADD(End_Date, 1) AS TimePoint
    FROM Input
),
OrderedTimePoints AS (
    -- 对每个起始周日的时间点去重并排序,生成序号
    SELECT 
        Base_Start,
        TimePoint,
        ROW_NUMBER() OVER (PARTITION BY Base_Start ORDER BY TimePoint) AS rn
    FROM (SELECT DISTINCT Base_Start, TimePoint FROM EventTimePoints) t
),
TimeIntervals AS (
    -- 用相邻时间点生成连续的事件区间
    SELECT 
        otp1.Base_Start,
        otp1.TimePoint AS Interval_Start,
        DATE_SUB(otp2.TimePoint, 1) AS Interval_End
    FROM OrderedTimePoints otp1
    JOIN OrderedTimePoints otp2 
        ON otp1.Base_Start = otp2.Base_Start 
        AND otp1.rn = otp2.rn - 1
    WHERE otp1.TimePoint < otp2.TimePoint
),
EventCoverage AS (
    -- 匹配每个区间对应的覆盖事件
    SELECT 
        ti.Base_Start,
        ti.Interval_Start,
        ti.Interval_End,
        etp.Event
    FROM TimeIntervals ti
    JOIN EventTimePoints etp 
        ON ti.Base_Start = etp.Base_Start
        AND etp.Start_Date <= ti.Interval_Start
        AND DATE_SUB(etp.TimePoint, 1) >= ti.Interval_End
)
-- 合并每个区间的事件,输出最终结果
SELECT 
    Base_Start AS Original_Start_Date,
    Interval_Start AS Period_Start,
    Interval_End AS Period_End,
    CONCAT_WS(',', COLLECT_SET(DISTINCT Event)) AS Merged_Events
FROM EventCoverage
GROUP BY Base_Start, Interval_Start, Interval_End
ORDER BY Base_Start, Interval_Start;

SQL Server 实现

适用于SQL Server 2017及以上版本(支持STRING_AGG函数),输入表结构同上:

WITH EventTimePoints AS (
    -- 提取同起始周日下所有事件的开始时间,以及结束时间+1(用于生成连续区间)
    SELECT 
        Start_Date AS Base_Start,
        Event,
        Start_Date AS TimePoint
    FROM Input
    UNION ALL
    SELECT 
        Start_Date AS Base_Start,
        Event,
        DATEADD(DAY, 1, End_Date) AS TimePoint
    FROM Input
),
OrderedTimePoints AS (
    -- 对每个起始周日的时间点去重并排序,生成序号
    SELECT 
        Base_Start,
        TimePoint,
        ROW_NUMBER() OVER (PARTITION BY Base_Start ORDER BY TimePoint) AS rn
    FROM (SELECT DISTINCT Base_Start, TimePoint FROM EventTimePoints) t
),
TimeIntervals AS (
    -- 用相邻时间点生成连续的事件区间
    SELECT 
        otp1.Base_Start,
        otp1.TimePoint AS Interval_Start,
        DATEADD(DAY, -1, otp2.TimePoint) AS Interval_End
    FROM OrderedTimePoints otp1
    JOIN OrderedTimePoints otp2 
        ON otp1.Base_Start = otp2.Base_Start 
        AND otp1.rn = otp2.rn - 1
    WHERE otp1.TimePoint < otp2.TimePoint
),
EventCoverage AS (
    -- 匹配每个区间对应的覆盖事件
    SELECT 
        ti.Base_Start,
        ti.Interval_Start,
        ti.Interval_End,
        etp.Event
    FROM TimeIntervals ti
    JOIN EventTimePoints etp 
        ON ti.Base_Start = etp.Base_Start
        AND etp.Start_Date <= ti.Interval_Start
        AND DATEADD(DAY, -1, etp.TimePoint) >= ti.Interval_End
)
-- 合并每个区间的事件,输出最终结果
SELECT 
    Base_Start AS Original_Start_Date,
    Interval_Start AS Period_Start,
    Interval_End AS Period_End,
    STRING_AGG(DISTINCT Event, ',') AS Merged_Events
FROM EventCoverage
GROUP BY Base_Start, Interval_Start, Interval_End
ORDER BY Base_Start, Interval_Start;

效果说明

以示例输入为例:

EventStart_DateEnd_Date
E12024-05-052024-05-25
E22024-05-052024-05-25
E32024-05-052024-06-01
E42024-05-122024-05-18

运行后输出结果:

Original_Start_DatePeriod_StartPeriod_EndMerged_Events
2024-05-052024-05-052024-05-25E1,E2,E3
2024-05-052024-05-262024-06-01E3
2024-05-122024-05-122024-05-18E4

完全符合需求:同起始周日的重叠事件合并,非重叠时段单独成行,不同起始周日的事件独立输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 15:30:22