我有一个系统,用户可以在该系统中预订不同日期和时间段的房间,在数据库中我们将保存bookingdate
,StartTime
和EndTime
,如下表所示,startime
和endtime
之间的最小间隔为30分钟。
MeetingDate -> Date (values like '6/4/2014','6/5/2014')
StartTime -> Time (values like '10:00:00', '11:00:00')
EndTime -> Time (values like '13:00:00', '14:00:00')
我需要定期检查所有日期的可用时间段,考虑到08:00 AM - 06:00 PM的时间限制,因为我创建了下面的cte表,它将列出所有时间段间隔30分钟
现在我想通过过滤来过滤每个日期的可用时间
通过将其与创建的'TimeSlots'
ste表匹配来预订时间
以上,或任何其他方法也可以
如果有任何需要进一步的信息请告诉我
答案 0 :(得分:1)
试试这个(原始输出):
create table Bookings (MeetingDate date, StartTime time, EndTime time);
insert into Bookings (MeetingDate, StartTime, EndTime) values
('2014-05-01', '9:15', '12:15'),
('2014-05-02', '8:00', '10:00'),
('2014-05-02', '10:30', '11:00'),
('2014-05-02', '11:00', '17:00'),
('2014-05-03', '09:00', '18:00');
with [times_between_0800_and_1800] as
(
select cast('08:00' as time) [time]
union all
select dateadd(minute, 10, [time])
from [times_between_0800_and_1800]
where [time] < '18:00'
)
,[distinct_dates] as
(
select distinct MeetingDate [date] from Bookings
)
,[dates_with_time] as
(
select cast(d.[date] as datetime) + cast(t.[time] as datetime) [value]
from [distinct_dates] d
cross join [times_between_0800_and_1800] t
)
select dt.*
from [dates_with_time] dt
left join Bookings b on dt.value between cast(b.MeetingDate as datetime) + cast(b.StartTime as datetime) and cast(b.MeetingDate as datetime) + cast(b.EndTime as datetime)
where b.MeetingDate is null
order by dt.value
U P D A T E
另一个更复杂的解决方案,它返回可用的时间段(精确到10分钟)
with [times_between_0800_and_1800] as
(
select cast('08:00' as time) [time]
union all
select dateadd(minute, 10, [time])
from [times_between_0800_and_1800]
where [time] < '18:00'
)
,[distinct_dates] as
(
select distinct MeetingDate [date] from Bookings
)
,[dates_with_time] as
(
select cast(d.[date] as datetime) + cast(t.[time] as datetime) [value]
from [distinct_dates] d
cross join [times_between_0800_and_1800] t
)
,[raw_available_times] as
(
select dt.value, cast(dt.value as date) [date]
from [dates_with_time] dt
left join Bookings b on dt.value between cast(b.MeetingDate as datetime) + cast(b.StartTime as datetime) and cast(b.MeetingDate as datetime) + cast(b.EndTime as datetime)
where b.MeetingDate is null
)
,[ranked] as
(
select [value]
, [date]
, rank() over(partition by [date] order by [value]) [rank]
from [raw_available_times]
)
,[islands] as
(
select r1.value, r1.[date], r1.[rank]
, r2.value [r2_value]
, rank() over(partition by case when r2.value is null then 1 else 0 end order by r1.value) [order]
from [ranked] r1
left join [ranked] r2 on r1.[date] = r2.[date]
and r1.[rank] = r2.[rank] + 1
and datediff(minute, r2.[value], r1.[value]) = 10
)
select i1.[date], i1.[value] [startdate]
, isnull(_max.value, _last.value) [enddate]
from [islands] i1
left join [islands] i2 on i1.[order] + 1 = i2.[order]
and i2.[r2_value] is null
outer apply (
select max(value) [value]
from [islands]
where value > i1.[value]
and value < i2.[value]) as _max
outer apply (
select max(value) [value]
from [islands]) as _last
where i1.[r2_value] is null;