I have a table
CREATE TABLE consumer_occurrence_restoration_times (
consumer_id INT,
start_time TIMESTAMP,
end_time TIMESTAMP
);
where the data is
INSERT INTO consumer_occurrence_restoration_times (consumer_id, start_time, end_time)
VALUES
(1, '2023-09-24 20:00:00', '2023-09-25 12:00:00'),
(2, '2023-09-24 21:00:00', '2023-09-25 13:00:00'),
(1, '2023-09-26 20:00:00', '2023-09-28 02:00:00'),
(3, '2023-09-25 19:00:00', '2023-09-26 10:00:00'),
(4, '2023-09-25 21:30:00', '2023-09-27 14:00:00'),
(5, '2023-09-25 21:30:00', '2023-09-25 22:00:00')
I want to insert this data into another table tbl_bifuraction using a query so that it inserts data for a day, i.e. start_time occurs on same day as end_time not after 00:00:00 hours of next day.
CREATE TABLE tbl_bifurcation (
consumer_id INT,
start_time TIMESTAMP,
end_time TIMESTAMP,
isdaydiff INT
);
consumer_occurrence_restoration_times table has data like this:
consumer_id start_time end_time
1 2023-09-24 20:00:00 2023-09-25 00:00:00
2 2023-09-24 21:00:00 2023-09-25 13:00:00
1 2023-09-26 20:00:00 2023-09-28 02:00:00
3 2023-09-25 19:00:00 2023-09-26 10:00:00
5 2023-09-25 21:30:00 2023-09-25 22:00:00
The insert query inserts the data from the consumer_occurrence_restoration_times table into another table named tbl_bifurcation. However, it needs to split the time intervals into separate days and insert them as individual rows, considering a day from start_time to end_time.
Also, isdaydiff goes 1 if some data has start time as ‘2023-09-26 20:00:00’ and end time is ‘2023-09-27 20:00:00’ but it stays 0 when end time is ‘2023-09-27 00:00:00’.
For example, if start_time is ‘2023-09-26 20:00:00’ and end_time is ‘2023-09-28 02:00:00’, I want to insert rows like this in tbl_bifuraction:
consumer_id | start_time | end_time | isdaydiff |
---|---|---|---|
1 | 2023-09-24 20:00:00 | 2023-09-25 00:00:00 | 0 |
2 | 2023-09-24 21:00:00 | 2023-09-25 00:00:00 | 1 |
2 | 2023-09-25 00:00:00 | 2023-09-25 13:00:00 | 1 |
1 | 2023-09-26 20:00:00 | 2023-09-27 02:00:00 | 1 |
1 | 2023-09-27 02:00:00 | 2023-09-28 00:00:00 | 1 |
1 | 2023-09-28 00:00:00 | 2023-09-28 02:00:00 | 1 |
3 | 2023-09-25 19:00:00 | 2023-09-26 00:00:00 | 1 |
3 | 2023-09-26 00:00:00 | 2023-09-26 10:00:00 | 1 |
5 | 2023-09-25 21:30:00 | 2023-09-25 22:00:00 | 0 |
Here, isdaysdiff = 1 (in all rows except first and last) when bifurcation is done, not in all cases.
Condition for updating isdaydiff
isdaydiff = 0 is only used when bifurcation of start date and end date is done, and bifurcation is only done when start date and end date does not fall on same day. It has nothing to do with consumer_id. Each row regardless of any data is a seperate row, no issue whatsoever with previous row. But same consumer will only have different rows when start_date in next row is greater than or equal to previous row end_date with same consumer_id.
The fiddle link is added for bifuracted_query
2
Answers
You may achieve this by dividing the time intervals into distinct days and calculating the isdaydiff flag using a combination of common table expressions (CTEs) and the UNION ALL operator. Try this SQL query to insert the data into the tbl_bifurcation table;
In this query I used recursive CTE DateRange to divide the time intervals into distinct days and determine the isdaydiff flag.This starts with the initial intervals keep adding new rows recursively until the entire interval is covered. The final result is entered into the tbl_bifurcation table after the results of each recursive phase are combined using the UNION ALL operator.
The tbl_bifurcation table generates the desired output from the query together with the accurate isdaydiff values.
Hope it works 🙂
You can first insert the records that don’t require splitting, then
UNION ALL
that with the selection that does. Usegenerate_series()
to spawn the in-between days. Demo:+case
conditionally restores the time part of start and end of the series of timestamps. Everything in between will only use midnights.extract()
to get dates, times and more fromtimestamp
. Since I only needed dates and times and bothdate
andtime
have their own types with pre-defined up- and downcasts, I used those instead.