从预订表计算空闲时间插槽

时间:2016-04-06 16:45:17

标签: 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之间进行。 我想要做的是获取/计算预订之前,之间和之后的空闲时间槽,始终为当前日期。

这可以在DB-Layer上进行,也许可以使用存储过程?有人可以帮我解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

使用以下示例数据:

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,则不会使用LEAD和LAG,因此您可以使用以下查询,假设您将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

**如果此帖已回答问题,请“标记为答案”

答案 1 :(得分:1)

这适用于您提供的数据

    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