sql - 在不使用循环或光标的情况下计算预约预约的可用会话
问题描述
这是一个非常简化的模型,但原理仍然存在。在给定时间之间存在可用资源可用的会话。如果您进行预订,它将与开始时间和持续时间一起存储在预订表中。
我可以像这样得到预订之间的差距
;with cte as (
select ROW_NUMBER() OVER (ORDER BY StartTime)sq, StartTime,DATEADD(MINUTE,Duration,StartTime) as EndTime, Duration
from @Reservations
)
select StartTime = a.EndTime , EndTime = b.StartTime
from cte a
INNER JOIN cte b on a.sq = b.sq - 1
我正在努力的地方是更新 AvailableSessions 以考虑预订。我想返回一个如下所示的结果集。简单地说,对于 AvailableSession 中的每个原始插槽,必须根据预留在插槽内的开始和结束位置将其拆分为更多的拆分。例如,对于 1600 的预订,第一个会话需要从 1520 到 1600 分成两部分,依此类推。
我可以想出使用游标和循环的方法,但我更喜欢基于集合的方法。我认为这是我目前的 sql 知识的极限。
'Quick Tennis', '2020-11-02 15:20','2020-11-02 16:00' -- the original session is split and ends when the first reservation starts
'Quick Tennis', '2020-11-02 16:10','2020-11-02 16:35'-- the gap between the first reservation ending and the second starting
'Quick Tennis', '2020-11-02 16:45','2020-11-02 1720' -- the gap between the 2nd reservation ending and the third starting
'Quick Tennis', '2020-11-02 17:30','2020-11-02 2000' -- `no reservations made yet so still a contagious block
declare @AvailableSession TABLE (
ID int,
Name varchar(50),
StartTime datetime,
EndTime datetime
)
insert into @AvailableSession VALUES (1, 'Quick Tennis', '2020-11-02 15:20','2020-11-02 17:30')
insert into @AvailableSession VALUES (2, 'Quick Tennis', '2020-11-02 17:30','2020-11-02 20:00')
declare @Reservations TABLE
(
StartTime datetime,
Duration int
)
insert into @Reservations VALUES ('2020-11-02 16:00',10)
insert into @Reservations VALUES ('2020-11-02 16:35',10)
insert into @Reservations VALUES ('2020-11-02 17:20',10)
解决方案
我认为以下应该有效。可以通过组合步骤/ CTE 来简化它,但这可能是遵循我的逻辑的最简单方法:
表创建和示例数据
create table reservations (session_id integer, StartTime datetime, duration integer);
create table sessions(session_id integer, StartTime datetime,EndTime datetime);
insert into sessions(session_id, StartTime ,EndTime)
values (1,'2020-12-03 16:00', '2020-12-03 18:00');
insert into reservations(session_id, StartTime , duration)
values
(1, '2020-12-03 16:00', 5) -- Reservation at start of session
(1, '2020-12-03 16:10', 15),
(1, '2020-12-03 16:40', 6),
(1, '2020-12-03 16:46', 3), -- Starts when previous reservation ends
(1, '2020-12-03 16:52', 17),
(1, '2020-12-03 17:26', 10),
(1, '2020-12-03 17:46', 6)
(1, '2020-12-03 17:55', 5); -- Ends at session end
生成可用槽的 SQL
--Format reservations so that they have a start and end date and a sequence
with calc_resv (session_id, StartTime, EndTime, seq) as
(
select
session_id
, StartTime
, dateadd(mi, duration, StartTime ) as EndTime
, cast(rank() over (partition by session_id order by StartTime ) as integer) as seq
from reservations
),
--Combine session and reservation data into 1 table
data_set (session_id, StartTime, EndTime, seq) as
(
select session_id , StartTime ,EndTime, 0
from sessions
union all
select cr.session_id, cr.StartTime, cr.EndTime, cr.seq
from calc_resv cr
),
--Calculate available slots by using the end time of current record with the start time of the next record
avail_slots (session_id, seq, NextStart, NextEnd) as
(
select
session_id, seq
,case when seq = 0 then StartTime else
EndTime end as NextStart
, isnull(lead(startTime) over (order by session_id, seq), (select s.EndTime from sessions s where ds.session_id = s.session_id)) as NextEnd
from data_set ds
)
select * from avail_slots
where NextStart <> NextEnd -- Case where 1st reservation starts at the start of the session or one reservation immediately follows another
;
结果数据集
session_id seq NextStart NextEnd
1 1 2020-12-03 16:05 2020-12-03 16:10
1 2 2020-12-03 16:25 2020-12-03 16:40
1 4 2020-12-03 16:49 2020-12-03 16:52
1 5 2020-12-03 17:09 2020-12-03 17:26
1 6 2020-12-03 17:36 2020-12-03 17:46
1 7 2020-12-03 17:52 2020-12-03 17:55
推荐阅读
- javascript - 如何使 svg 图像不可拖动和可点击
- android - problem in applying custom background to layout with radius in corners
- sql - 如何消除多个服务器调用 | 微软 SQL 服务器
- node.js - Basic post request for users using express (React)
- python - Access each element of a multidimensional array without knowing the individual dimensions
- javascript - 测试函数中的javascript正则表达式错误?
- spring - Spring Boot 验证在整数字段中采用浮点值
- python - 更新python中嵌套循环中的列
- python - 如何保护 Python 脚本 SQL Server 身份验证
- kotlin - Kotlin Exposed Sum on condition (CaseWhenElse)