Sql server 从预订表计算空闲时间段

Sql server 从预订表计算空闲时间段,sql-server,tsql,Sql Server,Tsql,我有一张预定的桌子 ('2016-04-06 09:00:00', '2016-04-06 09:15:00'), ('2016-04-06 11:00:00', '2016-04-06 11:30:00'), ('2016-04-06 12:00:00', '2016-04-06 12:45:00'), ('2016-04-06 16:30:00', '2016-04-06 16:45:00'), 只能在07:00至19:00之间预订。 我想做的是,获取/计算预订之间、之前和之后的空闲时间,

我有一张预定的桌子

('2016-04-06 09:00:00', '2016-04-06 09:15:00'),
('2016-04-06 11:00:00', '2016-04-06 11:30:00'),
('2016-04-06 12:00:00', '2016-04-06 12:45:00'),
('2016-04-06 16:30:00', '2016-04-06 16:45:00'),
只能在07:00至19:00之间预订。 我想做的是,获取/计算预订之间、之前和之后的空闲时间,始终为当前日期


这是否可以在DB层上实现,或者使用存储过程?有人能帮我解决这一点吗?

这适用于您提供的数据

    select * into #t from (

select '2016-04-06 09:00:00'r_start , '2016-04-06 09:15:00'r_end union all 
select'2016-04-06 11:00:00', '2016-04-06 11:30:00'union all 
select'2016-04-06 12:00:00', '2016-04-06 12:45:00'union all 
select'2016-04-06 16:30:00', '2016-04-06 16:45:00') x

--returns duration between 1st reservation and the next   
select  
datediff(MINUTE,x.r_end,y.r_start)/60 'hours'
,datediff(MINUTE,x.r_end,y.r_start) - datediff(MINUTE,x.r_end,y.r_start)/60 * 60 'minutes'
,x.r_start
,x.r_end
from
(select r_start ,r_end
,row_number() over (order by r_start asc) rowid
from #t) x
left join (select r_start ,r_end
,row_number() over (order by r_start asc) rowid
from #t) y
on x.rowid = y.rowid - 1


--returns unreserved dates 
select  
x.r_end available_from
,y.r_start available_to
from
(select r_start ,r_end
,row_number() over (order by r_start asc) rowid
from #t) x
left join (select r_start ,r_end
,row_number() over (order by r_start asc) rowid
from #t) y
on x.rowid = y.rowid - 1

使用以下样本数据:

select * into #t from (
select 1 ID, '2016-04-06 09:00:00' r_start , '2016-04-06 09:15:00' r_end union
select 2, '2016-04-06 11:00:00', '2016-04-06 11:30:00'union
select 3, '2016-04-06 12:00:00', '2016-04-06 12:45:00'union
select 4, '2016-04-06 16:30:00', '2016-04-06 16:45:00') AS bookdata
以下查询将显示所有空闲时间段的结果:

;with booked as (
    select r_start, r_end
    , LAG(r_end) over (order by r_end) PrevBook
    , LEAD(r_start) over (order by r_start) NextBook
    from #t
)
select IsNull(PrevBook, '2016-04-06 07:00:00') AS FreeStart, r_start AS FreeEnd
from booked
union
select r_end, IsNull(NextBook, '2016-04-06 19:00:00')
from booked
结果

+---------------------+---------------------+
|      FreeStart      |       FreeEnd       |
+---------------------+---------------------+
| 2016-04-06 07:00:00 | 2016-04-06 09:00:00 |
| 2016-04-06 09:15:00 | 2016-04-06 11:00:00 |
| 2016-04-06 11:30:00 | 2016-04-06 12:00:00 |
| 2016-04-06 12:45:00 | 2016-04-06 16:30:00 |
| 2016-04-06 16:45:00 | 2016-04-06 19:00:00 |
+---------------------+---------------------+
如果您使用的是2012年以前的SQL,那么您将不会有超前和滞后,所以您可以使用下面的查询,假设您的ID是主键

;with booked as (
    select r_start, r_end
    , (select top 1 r_end from #t where ID < tbl.ID order by ID desc) PrevBook
    , (select top 1 r_start from #t where ID > tbl.ID order by ID) NextBook
    from #t tbl
)
select IsNull(PrevBook, '2016-04-06 07:00:00') AS FreeStart, r_start AS FreeEnd
from booked
union
select r_end, IsNull(NextBook, '2016-04-06 19:00:00')
from booked

**如果这篇文章已经回答了问题,请标记为答案

任何你感到累的代码?我试过你的答案。我得到了一个我无法理解的结果。请将结果包含在您的答案中并解释它好吗?嗨,Flicker,我使用的是SQL Server 2008。滞后和超前在2008年不起作用。我怎么能重写那两行呢?嗯,这有点复杂。您的表中有整数主键吗?是的,我的表中有整数主键我的第一个查询中有一个额外的逗号。但是我的查询返回的正是您在结果部分看到的结果。它包括07:00到09:00和16:45到19:00。我想问题是我在表中的日期时间也不同。例如2016-02-01或2016-02-02。所以约会时间是混合的。。。