I am trying to calculate the total opening time in hours for each hotel. Each day (d1 - d7) the time can be different and a range is given for which that time is applicable. For example row 1 tells us that during the time period 2020-05-15 till 2020-12-31 the hotel is open for 1 hour(9:00 - 10:00) for d2 and for d1 it's not opened.
the issue here is that we have overlapping dates and time. Looking at d2 the shop opens from 9:00 till 10:00 [1 hour] from May 15th till end December 31st. But row 2 shows that from August 27th till December 31st the shop opens for another additional hour (13:00 -14:00pm. So the total hours should be 2 for the range (2020-08-27 to 2020-12-31).
Looking at the data it looks like running total is needed but row 6th shows that it opens for 1 hour but in that case we can't add the previous sum of hours of row 4 and row 5 since their from and till dates are not overlapping with the date range of row 6. But row 1-3 do overlap with row 6 so they should be added.
There are similar cases like these, and there are also cases where we just have 1 row for 1 hotel. Looking at all the cases I am stuck in calculating the hours per d1,d2 for a given time range (from - till)
hotel d1_from d1_to d2_from d2_to from till
1 00:00:00 00:00:00 09:00:00 10:00:00 2020-05-15 2020-12-31
1 00:00:00 00:00:00 13:00:00 14:00:00 2020-08-27 2020-12-31
1 00:00:00 00:00:00 15:00:00 16:00:00 2020-09-11 2020-12-31
1 09:30:00 10:15:00 18:00:00 19:00:00 2020-11-24 2020-11-25
1 00:00:00 00:00:00 20:00:00 21:00:00 2020-11-25 2020-11-25
1 09:30:00 10:15:00 22:00:00 23:00:00 2020-12-01 2020-12-03
select
d1_from,
d1_to,
d2_from,
d2_to,
timediff('minute',d1_from,d1_to) /60 as d1_total,
timediff('minute',d2_from,d2_to)/60 as d2_total,
case
when from >= lead(from)over(partition by hotel ORDER by from)
then lead(from)over(partition by hotel ORDER by from)
else null end as date_adjustment,
sum(d2_total) over (partition by hotel order by from) as cumulative_d2,
sum(d1_total) over (partition by hotel order by from) as cumulative_d1
from table
d2_hours (new column)
1 --first row only i.e 9 - 10
2 --first two rows 9- 10 and 13 - 14
3 --first, 2nd and 3rd rows 9-10, 13 - 14 , 15 - 16
4 -- first 4 rows added
5 -- first 5 rows
3 --first 3 rows added only] --> since 2020-12-01 (from) doesn't overlap with the "till" date of the previous row
-- so for each day the logic should be created d1_hours, d2_hours d3_hours etc..
One option is to count the weeks and sum the weekday hours.
WITH CTE AS
(SELECT 1 HOTEL, '00:00:00' MONDAY_START, '00:00:00' MONDAY_FINISH, '09:00:00'TUESDAY_START, '10:00:00' TUESDAY_FINISH, '2020-05-15'::DATE FROM_DATE, '2020-12-31'::DATE TILL_DATE UNION ALL
SELECT 1 HOTEL, '00:00:00' MONDAY_START, '00:00:00' MONDAY_FINISH, '13:00:00'TUESDAY_START, '14:00:00' TUESDAY_FINISH, '2020-08-27'::DATE FROM_DATE, '2020-12-31'::DATE TILL_DATE UNION ALL
SELECT 1 HOTEL, '00:00:00' MONDAY_START, '00:00:00' MONDAY_FINISH, '15:00:00'TUESDAY_START, '16:00:00' TUESDAY_FINISH, '2020-09-11'::DATE FROM_DATE, '2020-12-31'::DATE TILL_DATE UNION ALL
SELECT 1 HOTEL, '09:30:00' MONDAY_START, '10:15:00' MONDAY_FINISH, '18:00:00'TUESDAY_START, '19:00:00' TUESDAY_FINISH, '2020-11-24'::DATE FROM_DATE, '2020-11-25'::DATE TILL_DATE UNION ALL
SELECT 1 HOTEL, '00:00:00' MONDAY_START, '00:00:00' MONDAY_FINISH, '20:00:00'TUESDAY_START, '21:00:00' TUESDAY_FINISH, '2020-11-25'::DATE FROM_DATE, '2020-11-25'::DATE TILL_DATE UNION ALL
SELECT 1 HOTEL, '09:30:00' MONDAY_START, '10:15:00' MONDAY_FINISH, '22:00:00'TUESDAY_START, '23:00:00' TUESDAY_FINISH, '2020-12-01'::DATE FROM_DATE, '2020-12-03'::DATE TILL_DATE )
SELECT * ,(WEEK(TILL_DATE)-WEEK(FROM_DATE)+1)*(DATEDIFF(HOUR,MONDAY_START::TIME,MONDAY_FINISH::TIME)+DATEDIFF(HOUR,TUESDAY_START::TIME,TUESDAY_FINISH::TIME)) YOUR_ANSWER FROM CTE ;
You can fiddle with day_of_week to get the edge cases just right. However I'll leave that to you as is makes the code somewhat messy and this just to give you an option of how to solve your problem.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.