This query will get you the list of potential overlap dates:
select start_date from records where ...
union
select end_date from records where ...
Now you can use that to process the records.
Here is an example (using Oracle so you would need to change some bits):
Code:
SQL> create table records
2 ( set_id int
3 , start_date date
4 , end_date date
5 );
Table created.
SQL> insert into records values (1, date '2006-01-01', date '2006-01-31');
1 row created.
SQL> insert into records values (1, date '2006-01-15', date '2006-01-20');
1 row created.
SQL> insert into records values (1, date '2006-01-17', date '2006-02-28');
1 row created.
SQL> insert into records values (1, date '2006-02-01', date '2006-03-31');
1 row created.
SQL> insert into records values (1, date '2006-01-28', date '2006-03-28');
1 row created.
SQL> commit;
Commit complete.
This finds all the overlap dates:
Code:
SQL> select start_date from records where set_id=1
2 union
3 select end_date from records where set_id=1;
START_DATE
-----------
01-JAN-2006
15-JAN-2006
17-JAN-2006
20-JAN-2006
28-JAN-2006
31-JAN-2006
01-FEB-2006
28-FEB-2006
28-MAR-2006
31-MAR-2006
10 rows selected.
This shows all the required split records:
Code:
SQL> select distinct greatest(r.start_date,d.overlap_date) new_start
2 , least(r.end_date,d.overlap_date) new_end
3 from records r,
4 ( select start_date as overlap_date
5 from records where set_id=1
6 union
7 select end_date as overlap_date
8 from records where set_id=1
9 ) d
10 where d.overlap_date between r.start_date and r.end_date;
NEW_START NEW_END
----------- -----------
01-JAN-2006 01-JAN-2006
15-JAN-2006 15-JAN-2006
17-JAN-2006 17-JAN-2006
20-JAN-2006 20-JAN-2006
28-JAN-2006 28-JAN-2006
31-JAN-2006 31-JAN-2006
01-FEB-2006 01-FEB-2006
28-FEB-2006 28-FEB-2006
28-MAR-2006 28-MAR-2006
31-MAR-2006 31-MAR-2006
10 rows selected.
You could insert those and delete the old rows, or you could use procedural code something like:
Code:
for each record where ... do
for each date in
( select start_date as overlap_date from records where ...
union
select end_date as overap_date from records where ...
) do
if overlap_date between start_date and end_date then
update record set end_date = overlap_date;
insert into record (start_date, end_date, ...) values (overlap_date, end_date);
end if;
end do;
end do;
That is very much pseudo-code and needs a lot of polish, but hopefully you get the idea?