我正在(在 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 经验,并且尝试将其他问题的答案调整为我的代码是行不通的 - 我发现的是连接多天的块。 非常感谢任何帮助。
我已经实现了上面的第一个表,但找不到到达第二个表的参考。
应与 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