clintnash
asked on
Find gaps in datetime columns (where starttime of next <> endtime of current)
I need to identify holes in a schedule, basically I am looking for missing data. Using the following data as a test case I need to identify any timeslots between the variables @daystart and @dayend where there isn't data.
The results would look like this.
Any advise or help is greatly appreciated.
Thank you...
LocID StartTime EndTime
1 11/15/2010 1:00pm 11/15/2010 2:00pm
1 11/15/2010 2:00pm 11/15/2010 3:00pm
1 11/15/2010 4:00pm 11/15/2010 5:00pm
1 11/15/2010 7:00pm 11/15/2010 8:00pm
Declare @daystart datetime
Declare @dayend datetime
Set @daystart = '12:00pm' --First appointment of the day
Set @dayend = '9:00pm' --Last appointment of the day
The results would look like this.
1 11/15/2010 12:00pm 11/15/2010 1:00pm
1 11/15/2010 3:00pm 11/15/2010 4:00pm
1 11/15/2010 5:00pm 11/15/2010 7:00pm
1 11/15/2010 8:00pm 11/15/2010 9:00pm
Any advise or help is greatly appreciated.
Thank you...
I probably know what you're going to say but I'll ask anyways. Are the "time slots" always in hour increments? If so, you could always join to a Time_Dimension type table.
ASKER
Unfortunately no. The time increments range from 15 minutes to 2 hours.
Something like this maybe? You can past the whole thing into SSMS and run it. Note: The table var I created is just for test and would be replaced by actual table data.
The logic behind it would be to use the RowNumber function to create a unique ID per location ID and use that RowNumber as part of a join to get the previous records value.
declare @myTable table (LocID int, StartTime datetime, EndTime datetime)
declare @startDateTime datetime = '11/15/2010 12:00 PM'
declare @endDateTime datetime = '11/15/2010 9:00 PM'
insert into @myTable values ( 1, '11/15/2010 1:00pm', '11/15/2010 2:00pm')
insert into @myTable values ( 1, '11/15/2010 2:00pm', '11/15/2010 3:00pm')
insert into @myTable values ( 1, '11/15/2010 4:00pm', '11/15/2010 5:00pm')
insert into @myTable values ( 1, '11/15/2010 7:00pm', '11/15/2010 8:00pm');
with MyTableWithStartAndEnd as
(
select 1 as LocId, @startDateTime as StartTime, @startDateTime as EndTime
union
select * from @myTable
union
select 1, @endDateTime as StartTime, @endDateTime as EndTime
)
, MyTableWithCounter as
(
select ROW_NUMBER() over (partition by LocId order by endtime) as Instance_Counter
, *
from MyTableWithStartAndEnd
)
, MyTableWithRanges as
(
select
a.[LocId]
,a.[StartTime]
,a.EndTime
,a.Instance_Counter
,abs((select datediff(minute, a.EndTime, b.StartTime) from MyTableWithCounter b where a.locId = b.LocID and b.[Instance_Counter] = a.[Instance_Counter] + 1)) as GapRangeInMinutes
from MyTableWithCounter a
)
select
StartTime
, DATEADD(MINUTE, GapRangeInMinutes, StartTime) as EndTime
, case
when GapRangeInMinutes < 60 then 0
else GapRangeInMinutes/60
end as GapInHours
, GapRangeInMinutes as GapInMinutes
from MyTableWithRanges
where ISNULL(GapRangeInMinutes,0 ) > 0
The logic behind it would be to use the RowNumber function to create a unique ID per location ID and use that RowNumber as part of a join to get the previous records value.
declare @myTable table (LocID int, StartTime datetime, EndTime datetime)
declare @startDateTime datetime = '11/15/2010 12:00 PM'
declare @endDateTime datetime = '11/15/2010 9:00 PM'
insert into @myTable values ( 1, '11/15/2010 1:00pm', '11/15/2010 2:00pm')
insert into @myTable values ( 1, '11/15/2010 2:00pm', '11/15/2010 3:00pm')
insert into @myTable values ( 1, '11/15/2010 4:00pm', '11/15/2010 5:00pm')
insert into @myTable values ( 1, '11/15/2010 7:00pm', '11/15/2010 8:00pm');
with MyTableWithStartAndEnd as
(
select 1 as LocId, @startDateTime as StartTime, @startDateTime as EndTime
union
select * from @myTable
union
select 1, @endDateTime as StartTime, @endDateTime as EndTime
)
, MyTableWithCounter as
(
select ROW_NUMBER() over (partition by LocId order by endtime) as Instance_Counter
, *
from MyTableWithStartAndEnd
)
, MyTableWithRanges as
(
select
a.[LocId]
,a.[StartTime]
,a.EndTime
,a.Instance_Counter
,abs((select datediff(minute, a.EndTime, b.StartTime) from MyTableWithCounter b where a.locId = b.LocID and b.[Instance_Counter] = a.[Instance_Counter] + 1)) as GapRangeInMinutes
from MyTableWithCounter a
)
select
StartTime
, DATEADD(MINUTE, GapRangeInMinutes, StartTime) as EndTime
, case
when GapRangeInMinutes < 60 then 0
else GapRangeInMinutes/60
end as GapInHours
, GapRangeInMinutes as GapInMinutes
from MyTableWithRanges
where ISNULL(GapRangeInMinutes,0
ASKER
I think this is almost there. The number of results are correct but the times in the results are not. I cut and pasted the code and am getting the following for output.
The results should be
It seems like after the first row that the rest of the timeslots are off by an hour? Thank you very much for your help.
Start Time End Time GinH GinMin
Nov 15 2010 12:00PM Nov 15 2010 1:00PM 1 60
Nov 15 2010 2:00PM Nov 15 2010 3:00PM 1 60
Nov 15 2010 4:00PM Nov 15 2010 6:00PM 2 120
Nov 15 2010 7:00PM Nov 15 2010 8:00PM 1 60
The results should be
Start Time End Time GinH GinMin
Nov 15 2010 12:00PM Nov 15 2010 1:00PM 1 60
Nov 15 2010 3:00PM Nov 15 2010 4:00PM 1 60
Nov 15 2010 5:00PM Nov 15 2010 7:00PM 2 120
Nov 15 2010 8:00PM Nov 15 2010 9:00PM 1 60
It seems like after the first row that the rest of the timeslots are off by an hour? Thank you very much for your help.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Brilliant! Thank you so much for your time. This was another opportunity to not just get an answer to a problem but learn something in the process. Thanks again...