Use below logic
Make a dimension called Dim_Hours and do a cross join with the table that contains begin and end timestamps.
dim_hour is a static table with data like this
--when the difference is +ve
-- 7 - 0 7 +ve
-- 7 - 1 6 +ve
-- 7 - 2 5 +ve
-- 7 - 3 4 +ve
-- 7 - 4 3 +ve
-- 7 - 5 2 +ve
-- 7 - 6 1 +ve
--when the difference is Zer0
-- 7 - 7 0 Zero
--when the difference is -ve
-- 7 - 8 -1 -ve
-- 7 - 9 -2 -ve
-- 7 - 10 -3 -ve
-- 7 - 11 -4 -ve
-- 7 - 12 -5 -ve
-- 7 - 13 -6 -ve
-- 7 - 14 -7 -ve
-- 7 - 15 -8 -ve
-- 7 - 16 -9 -ve
-- 7 - 17 -10 -ve
-- 7 - 18 -11 -ve
-- 7 - 19 -12 -ve
-- 7 - 20 -13 -ve
-- 7 - 21 -14 -ve
-- 7 - 22 -15 -ve
-- 7 - 23 -16 -ve
Make a dimension called Dim_Hours and do a cross join with the table that contains begin and end timestamps.
dim_hour is a static table with data like this
Hour_Number | Hour_Label | Hour_Order |
0 | 12:00 AM | 19 |
1 | 1:00 AM | 20 |
2 | 2:00 AM | 21 |
3 | 3:00 AM | 22 |
4 | 4:00 AM | 23 |
5 | 5:00 AM | 24 |
6 | 6:00 AM | 1 |
7 | 7:00 AM | 2 |
8 | 8:00 AM | 3 |
9 | 9:00 AM | 4 |
10 | 10:00 AM | 5 |
11 | 11:00 AM | 6 |
12 | 12:00 PM | 7 |
13 | 1:00 PM | 8 |
14 | 2:00 PM | 9 |
15 | 3:00 PM | 10 |
16 | 4:00 PM | 11 |
17 | 5:00 PM | 12 |
18 | 6:00 PM | 13 |
19 | 7:00 PM | 14 |
20 | 8:00 PM | 15 |
21 | 9:00 PM | 16 |
22 | 10:00 PM | 17 |
23 | 11:00 PM | 18 |
--when the difference is +ve
-- 7 - 0 7 +ve
-- 7 - 1 6 +ve
-- 7 - 2 5 +ve
-- 7 - 3 4 +ve
-- 7 - 4 3 +ve
-- 7 - 5 2 +ve
-- 7 - 6 1 +ve
--when the difference is Zer0
-- 7 - 7 0 Zero
--when the difference is -ve
-- 7 - 8 -1 -ve
-- 7 - 9 -2 -ve
-- 7 - 10 -3 -ve
-- 7 - 11 -4 -ve
-- 7 - 12 -5 -ve
-- 7 - 13 -6 -ve
-- 7 - 14 -7 -ve
-- 7 - 15 -8 -ve
-- 7 - 16 -9 -ve
-- 7 - 17 -10 -ve
-- 7 - 18 -11 -ve
-- 7 - 19 -12 -ve
-- 7 - 20 -13 -ve
-- 7 - 21 -14 -ve
-- 7 - 22 -15 -ve
-- 7 - 23 -16 -ve
use the above explanation to write your SQL
WITH TEMP AS (SELECT [ID] , [On_DateTime] , [Off_DateTime] , [On_Duration_Minutes] , dh.Hour_Number FROM [dbo].[tableWithData] f CROSS JOIN dim_Hour dh WHERE 1=1 )--when -ve and hour part matches start of hour SELECT t.*, [On_DateTime], dateadd(HOUR, datediff(HOUR, 0, dateadd(mi, 60, [On_DateTime])), 0), DATEDIFF(SECOND, [On_DateTime], dateadd(HOUR, datediff(HOUR, 0, dateadd(mi, 60, [On_DateTime])), 0))/60.0 on_Duration_minutes_Derived FROM TEMP t WHERE 1=1 AND datepart(HH, [On_DateTime]) - datepart(HH, [Off_DateTime]) <= -1 AND t.Hour_Number =datepart(HH, [On_DateTime]) UNION --when -ve and hour part matches end of hour SELECT t.*, dateadd(HOUR, datediff(HOUR, 0, [Off_DateTime]), 0), [Off_DateTime], DATEDIFF(SECOND, dateadd(HOUR, datediff(HOUR, 0, [Off_DateTime]), 0), [Off_DateTime])/60.0 on_Duration_minutes_Derived FROM TEMP t WHERE 1=1 AND datepart(HH, [On_DateTime]) - datepart(HH, [Off_DateTime]) <= -1 AND t.Hour_Number =datepart(HH, [Off_DateTime]) UNION --when -ve and hour part between start and end of hour excludint boundries SELECT t.*, dateadd(HOUR, datediff(HOUR, 0, [Off_DateTime]), 0), [Off_DateTime], 60.00 on_Duration_minutes_Derived FROM TEMP t WHERE 1=1 AND datepart(HH, [On_DateTime]) - datepart(HH, [Off_DateTime]) <= -1 AND t.Hour_Number >datepart(HH, [On_DateTime]) AND t.Hour_Number< datepart(HH, [Off_DateTime]) UNION --when 0 and hour part matches with start/end SELECT t.*, dateadd(HOUR, datediff(HOUR, 0, [Off_DateTime]), 0), [Off_DateTime], CASE WHEN on_Duration_minutes<0 THEN 0 ELSE on_Duration_minutes END on_Duration_minutes_Derived FROM TEMP t WHERE 1=1 AND datepart(HH, [On_DateTime]) - datepart(HH, [Off_DateTime]) = 0 AND t.Hour_Number=datepart(HH, [On_DateTime]) UNION --when +ve and hour part matches start of hour SELECT t.*, [On_DateTime], dateadd(HOUR, datediff(HOUR, 0, dateadd(mi, 60, [On_DateTime])), 0), DATEDIFF(SECOND, [On_DateTime], dateadd(HOUR, datediff(HOUR, 0, dateadd(mi, 60, [On_DateTime])), 0))/60.0 on_Duration_minutes_Derived FROM TEMP t WHERE 1=1 AND datepart(HH, [On_DateTime]) - datepart(HH, [Off_DateTime]) >= 1 AND t.Hour_Number =datepart(HH, [On_DateTime]) UNION --when +ve and hour part matches end of hour SELECT t.*, dateadd(HOUR, datediff(HOUR, 0, [Off_DateTime]), 0), [Off_DateTime], DATEDIFF(SECOND, dateadd(HOUR, datediff(HOUR, 0, [Off_DateTime]), 0), [Off_DateTime])/60.0 on_Duration_minutes_Derived FROM TEMP t WHERE 1=1 AND datepart(HH, [On_DateTime]) - datepart(HH, [Off_DateTime]) >= 1 AND t.Hour_Number =datepart(HH, [Off_DateTime]) UNION --when +ve and hour part between start of hour and end of hour SELECT t.*, dateadd(HOUR, datediff(HOUR, 0, [Off_DateTime]), 0), [Off_DateTime], 60.00 on_Duration_minutes_Derived FROM TEMP t WHERE 1=1 AND datepart(HH, [On_DateTime]) - datepart(HH, [Off_DateTime]) >= 1 AND t.Hour_Number!=datepart(HH, [On_DateTime]) AND t.Hour_Number!=datepart(HH, [Off_DateTime]) AND (t.Hour_Number <datepart(HH, [Off_DateTime]) OR t.Hour_Number > datepart(HH, [On_DateTime])) ORDER BY 2, 3, 4
No comments:
Post a Comment