每日计划 - 将多个时间段“连接”成一个块

问题描述 投票:0回答:1

我正在(在 SQL Server 2016 中)制定牙科时间表,并使用 LEAD(通过 PARTITION ... 我可以生成这种格式的数据:

椅子 日期 开始时间 结束时间 已封锁 已预订 会议
分 1 2025-03-03 490 500 1 0
分 1 2025-03-03 500 510 1 0
分 1 2025-03-03 510 520 0 0 后续
分 1 2025-03-03 520 530 0 0 后续
分 1 2025-03-03 530 540 0 0 后续
分 1 2025-03-03 540 550 0 0 后续
分 1 2025-03-03 550 560 0 1
分 1 2025-03-03 560 570 0 1
分 1 2025-03-03 570 580 0 1
分 1 2025-03-03 580 590 0 1
分 1 2025-03-03 590 600 0 0 后续
分 1 2025-03-03 600 610 0 0 评估
分 1 2025-03-03 610 620 0 0 评估
分 1 2025-03-03 620 630 0 0 评估

我需要实现的目标(并且无法在本论坛的其他地方找到)是将数据分组在一起以生成:

椅子 日期 开始时间 结束时间 标签
分 1 2025-03-03 490 510 阻止
分 1 2025-03-03 510 550 后续
分 1 2025-03-03 550 590 已预订
分 1 2025-03-03 590 600 后续
分 1 2025-03-03 600 630 评估

即,如果最后 3 列的值与之前的行相比没有变化,则它们将被添加到连续的块中。此示例适用于跟进是从 510 到 600 的单个会话,但随后被预订的预约覆盖的情况。

时间值是午夜过后的分钟;它们将在展示阶段发生变化。

我没有 CTE 经验,并且尝试将其他问题的答案调整为我的代码是行不通的 - 我发现的是连接多天的块。 非常感谢任何帮助。

我已经实现了上面的第一个表,但找不到到达第二个表的参考。

sql sql-server sql-server-2016 schedule
1个回答
0
投票

应与 CTE、LAG() 和 ROW_NUMBER() 一起使用。在 SQL 2017 上测试。

;With
    alfa
    as
    (
        -- Assign new Session value depend of Blocked & Booked status
        SELECT Chair, Date, StartTime, EndTime,
        CASE 
            WHEN Blocked = 1 THEN 'Block'
            WHEN Booked = 1  THEN 'Booked'
            WHEN [Session] is null Then ''
            ELSE [Session]
        END as Session
        FROM _test
    ),
    bravo
    as
    (
        -- Compare this with the previous row and assign isNew flag
        SELECT *,
        CASE 
            WHEN LAG(Session,1) OVER(ORDER BY Chair,DATE,StartTime) = Session THEN 0
            ELSE 1
        END isNew
        FROM alfa
    ),
    charlie
    as
    (
        -- Get the very Last changing slot and assign it's StartTime as PreviousStartTime one for the current slot
        SELECT *,
            CASE 
                WHEN isNew = 1 THEN StartTime
                ELSE (
                        SELECT TOP 1
                            StartTime
                        FROM bravo x
                        WHERE x.Chair = b.Chair AND x.[Date] = b.[Date] AND x.[Session] = b.[Session]
                            AND x.isNew = 1 AND x.StartTime < b.StartTime
                        ORDER BY Chair,[Date],StartTime desc
                    ) END as PreviousStartTime
        FROM bravo b
    ),
    delta
    as
    (
        -- Get Partitioned Order on the PreviousStartTime descending for each slot to filter on last step
        SELECT *,
            ROW_NUMBER() OVER(PARTITION BY Chair,Date,PreviousStartTime ORDER BY Chair,DATE, EndTime desc) rn
        FROM charlie
    )
    
SELECT Chair, [Date], PreviousStartTime as StartTime, EndTime, [Session]
    FROM delta
WHERE rn = 1
ORDER BY Chair,[Date],StartTime
© www.soinside.com 2019 - 2024. All rights reserved.