Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

So geben Sie alle freien Zeiträume aus einem Terminset zurück

Es ist schwer zu sagen, ob die folgende Lösung angesichts der kleinen Datenprobe für Sie funktioniert, aber hoffentlich wird sie Ihnen den Einstieg erleichtern.

IF OBJECT_ID('tempdb..#sked') is not null
DROP TABLE #sked

IF OBJECT_ID('tempdb..#tmpResults') is not null
DROP TABLE #tmpResults

create table #sked(
    ID int,
    time_start datetime2,
    time_end datetime2,
    duration int)

insert into #sked (ID,time_start,time_end,duration) values
(4,'2016-06-06 00:30:00','2016-06-06 01:30:00',3600000),
(2,'2016-06-06 04:00:00','2016-06-06 04:20:00',1200000),
(1,'2016-06-06 10:00:00','2016-06-06 11:00:00',3600000),
(6,'2016-06-06 11:30:00','2016-06-06 12:30:00',3600000)

declare @startRange datetime2
declare @endRange datetime2
declare @slotDurationInMinutes int

set @startRange = '2016-06-05T00:00:00.000'
set @endRange = '2016-06-07T21:59:00.000'
set @slotDurationInMinutes = 30

select
    time_end as free_from,
    isnull(lead(time_start) over (order by time_end),@endRange) as free_until
into #tmpResults
from
    #sked
where
    time_end >= @startRange 
    and time_end <= @endRange
    --and duration <= (@slotDurationInMinutes * 60000) --conversion to milliseconds

union all

select
    case when @startRange < min(time_start) then @startRange end as free_from,
    case when @startRange < min(time_start) then min(time_start) end as free_until
from
    #sked
where
    time_end >= @startRange 
    and time_end <= @endRange
    --and duration <= (@slotDurationInMinutes * 60000) --conversion to milliseconds
order by
    free_from

select 
    *,
    DATEDIFF(minute,free_from,free_until) 
from 
    #tmpResults
where
    free_from is not null
    and DATEDIFF(minute,free_from,free_until) >= @slotDurationInMinutes