2014-09-05 69 views
4

我有一个包含给定日期中可变时间范围的保留表。它们是30分钟,60分钟,用户输入的任何给定分钟范围的预留时间段。SQL提取一天中未保留的所有30分钟或60分钟的时间段

我想要做的是创建一个SQL语句,可以给我所有的时间段在给定的一天,不保留。用户可以指定分钟范围(30分钟,60分钟,90分钟)。我甚至从哪里开始?

保留表是基本的:

ROOM, RESERVED_DATE, FROM_TIME, TO_TIME 
A  09/02/2014  9:00 AM 10:00 AM 
B  09/02/2014  11:00 AM 12:00 PM 
C  09/02/2014  1:30 PM 2:00 PM 

我会允许用户说,他们希望工作时间(8:00 AM - 4:30 PM)之间的所有可用的房间是一个特定的增量内(30分钟,60分钟,90分钟)。

+2

您需要从具有所有可用时间段的表开始。然后你做一个左边加入你的保留。 – 2014-09-05 14:43:51

+1

保留时间是否总是在30分钟以内,或者您是否可以在9:13 - 9:43之间进行预约? – SQLChao 2014-09-05 15:13:24

+0

我会说,一般来说,他们会在一个半小时的时间内落下。他们可能会陷入宿舍,尽管这很少见。 – jlrolin 2014-09-05 17:27:11

回答

0

这是我会采取的方法。这需要您的@minimum_interval并找到一个大于此值的时间间隔。正如所写,它不包括前后。您可以通过在表格中插入一个虚拟日期作为开始日期/时间和结束日期/时间,或者将它建立为cte中的联合(首选)来解决该问题。

基本上,它所做的全部工作都是按开始时间对[to]列和[next]列进行日期排序,其中[next]用滞后函数进行计算。这使你不必拥有一张专用的表格,这也是为什么我要在cte中建立一个虚拟的开始和结束会议的原因;由于数据未被存储,因此不必更新。您可以将开始和结束时间存储在元数据结构中,以便为不同房间设置不同的“开放”时段。

另外,您可以将PARTITION子句添加到滞后函数中,以使其无需指定房间即可工作。

这是一个有趣的练习,感谢您提出这个问题!

declare @date [datetime] = cast(current_timestamp as [date]); 
declare @minimum_interval [int] = 15 
    , @room   [sysname] = N'A'; 
declare @reservation table (
[room] [sysname] 
, [from] [datetime] 
, [to] [datetime]); 
insert into @reservation 
     ([room],[from],[to]) 
values  (N'A',N'20140902 09:00',N'20140902 10:00'), 
     (N'A',N'20140902 10:00',N'20140902 11:00'), 
     (N'A',N'20140902 13:00',N'20140902 14:00'); 
with [builder] 
as (select [room] 
      , [from] 
      , [to] 
      , lag ([from] 
        , 1 
        , 0) 
       over (
        order by [from] desc) as [next] 
    from @reservation 
    where [room] = @room) 
select [room] 
    , [from] 
    , [to] 
    , [next] 
from [builder] 
where datediff(minute 
      , [to] 
      , [next]) > @minimum_interval; 
+0

这是正确的。原来的问题没有说明一个版本,所以我没有理由不使用什么是当前版本,即SQL Server 2012。 – 2014-09-08 14:14:31