I need to copy each row as many times as how many hours there are between StartTime and EndTime.
Example data:
TimeKey HourKey SensorKey IdleTimeMinute StartTime EndTime
20121017 8 45 110 2012.10.17 08:31 2012.10.17 10:21
20121017 10 45 25 2012.10.17 10:26 2012.10.17 10:51
20121017 12 45 5 2012.10.17 12:21 2012.10.17 12:26
20121017 12 45 60 2012.10.17 12:41 2012.10.17 13:41
20121017 13 45 55 2012.10.17 13:51 2012.10.17 14:46
20121017 15 45 5 2012.10.17 15:11 2012.10.17 15:16
20121017 15 45 35 2012.10.17 15:46 2012.10.17 16:21
20121017 18 45 5 2012.10.17 18:51 2012.10.17 18:56
Explanation
For example, the first row spans the hours 8, 9, and 10. In each of the three output rows, IdleTimeMinute needs to be the minutes duration within that hour.
Expected Result:
TimeKey HourKey SensorKey IdleTimeMinute StartTime EndTime
20121017 8 45 29 2012.10.17 08:31 2012.10.17 10:21
20121017 9 45 60 2012.10.17 08:31 2012.10.17 10:21
20121017 10 45 21 2012.10.17 08:31 2012.10.17 10:21
20121017 10 45 25 2012.10.17 10:26 2012.10.17 10:51
20121017 12 45 5 2012.10.17 12:21 2012.10.17 12:26
20121017 12 45 19 2012.10.17 12:41 2012.10.17 13:41
20121017 13 45 41 2012.10.17 12:41 2012.10.17 13:41
20121017 13 45 9 2012.10.17 13:51 2012.10.17 14:46
20121017 14 45 46 2012.10.17 13:51 2012.10.17 14:46
20121017 15 45 5 2012.10.17 15:11 2012.10.17 15:16
20121017 15 45 14 2012.10.17 15:46 2012.10.17 16:21
20121017 16 45 21 2012.10.17 15:46 2012.10.17 16:21
20121017 18 45 5 2012.10.17 18:51 2012.10.17 18:56
Smaller Example
Smaller example from first two lines:
TimeKey HourKey SensorKey IdleTimeMinute StartTime EndTime
20121017 8 45 110 2012.10.17 08:31 2012.10.17 10:21
20121017 10 45 25 2012.10.17 10:26 2012.10.17 10:51
For first line we have time 8:31 - 10:21 so In 8 Hour 29 Minutes, In 9 Hour 60 Minutes, In 10 Hour 21 Minute.
Expected small result:
TimeKey HourKey SensorKey IdleTimeMinute StartTime EndTime
20121017 8 45 29 2012.10.17 08:31 2012.10.17 10:21
20121017 9 45 60 2012.10.17 08:31 2012.10.17 10:21
20121017 10 45 21 2012.10.17 08:31 2012.10.17 10:21
20121017 10 45 25 2012.10.17 10:26 2012.10.17 10:51
Here you go. This will handle even cases where the span of time passes midnight or goes over many days. It should perform very well.
See the SqlFiddle for it.
I included the new timespan for the selected hour. If you want that timespan to end at
:59instead of:00of the next hour, then in the thirdCROSS APPLYchangeDateAdd(hour, 1, D.AnchorHour)toDateAdd(minute, 59, D.AnchorHour)and add+ 1to the end ofDateDiff(minute, S.HourStartTime, E.HourEndTime)in theSELECTclause.In my opinion:
Note: the reason I declare the @MaxHour variable is that the on-the-fly numbers table CTE I’m using wants a constant. Well, that’s not exactly accurate, but the long and short of it is that without a constant it can choose an execution plan that doesn’t limit the rows in the place needed to get a speedy query. I chose
DateDiffto compute this, but in fact I see now that this would probably be faster, and definitely would be faster if you have an index on IdleTimeMinute:Since the smallest time range that can span two different hours is 2 minutes (say 11:59 to 12:00) then we have to add 118 minutes to be sure to get at least 2 hours out of it.