oracle-databasedate

Split timeperiods by referring dates in another table


I have data in 2 tables with different timeperiods. I need to split/squeeze dates in table1 to make the records effective only for the duration available in table2 in Oracle.

Table1

Rec#   Col1    startdate           enddate
-------------------------------------------
1       A      15-Sep-24       31-Oct-24
2       A      1-Jan-25        20-Feb-25
3       A      8-Mar-25        31-Dec-99

Table2

Rec#   Col1    startdate           enddate
-------------------------------------------
1       A      20-Sep-24       15-Oct-24
2       A      20-Oct-24       10-Nov-24
3       A      15-Mar-25       1-Jun-25

Expected output from Table1

  1. Rec1 from table1 split into 2 records
  2. Rec2 completely ignored as no overlap with any records in table2
  3. Rec3 squeezed as per dates in rec3 of table2
Rec#   Col1    startdate           enddate
-------------------------------------------
1       A      20-Sep-24       15-Oct-24
1       A      20-Oct-24       31-Oct-24 
3       A      15-Mar-25       1-Jun-25

One way I can think of is below. But if enddate is 31-dec-9999 for any record, day level records will be too high which is not recommended.

  1. to get down records from table1 to day level
  2. pick only records that overlap with data in table2
  3. group them to periods where they are consecutive

Below are create table DDls

Create table table1 as
select 'A' col1,to_date('15-09-2024','DD-MM-YYYY') startdate, to_date('31-10-2024','DD-MM-YYYY') enddate from dual
union
select 'A',to_date('01-01-2025','DD-MM-YYYY') startdate, to_date('20-02-2025','DD-MM-YYYY') enddate from dual
union
select 'A',to_date('08-03-2025','DD-MM-YYYY') startdate, to_date('31-12-9999','DD-MM-YYYY') enddate from dual;

Create table table2 as
select 'A' col1,to_date('20-09-2024','DD-MM-YYYY') startdate, to_date('15-10-2024','DD-MM-YYYY') enddate from dual
union
select 'A',to_date('20-10-2024','DD-MM-YYYY') startdate, to_date('10-11-2024','DD-MM-YYYY') enddate from dual
union
select 'A',to_date('15-03-2025','DD-MM-YYYY') startdate, to_date('01-06-2025','DD-MM-YYYY') enddate from dual;

Thanks in advance


Solution

  • You can JOIN the two tables when the ranges overlap and then use GREATEST and LEAST:

    SELECT t1.col1,
           GREATEST(t1.startdate, t2.startdate) AS startdate,
           LEAST(t1.enddate, t2.enddate) AS enddate
    FROM   table1 t1
           INNER JOIN table2 t2
           ON (   t1.col1      = t2.col1
              AND t1.startdate < t2.enddate
              AND t2.startdate < t1.enddate)
    

    Which, for the sample data:

    CREATE TABLE table1 (col1, startdate, enddate) AS
    SELECT 'A', DATE '2024-09-15',  DATE '2024-10-31' FROM DUAL UNION ALL
    SELECT 'A', DATE '2025-01-01',  DATE '2025-02-20' FROM DUAL UNION ALL
    SELECT 'A', DATE '2025-03-08',  DATE '9999-12-31' FROM DUAL;
    
    CREATE TABLE table2 (col1, startdate, enddate) AS
    SELECT 'A', DATE '2024-09-20',  DATE '2024-10-15' FROM DUAL UNION ALL
    SELECT 'A', DATE '2024-10-20',  DATE '2024-11-10' FROM DUAL UNION ALL
    SELECT 'A', DATE '2025-03-15',  DATE '2025-06-01' FROM DUAL;
    

    Outputs:

    COL1 STARTDATE ENDDATE
    A 2024-09-20 00:00:00 2024-10-15 00:00:00
    A 2024-10-20 00:00:00 2024-10-31 00:00:00
    A 2025-03-15 00:00:00 2025-06-01 00:00:00

    fiddle