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