I have a table with the following data
PKey Start End Type
==== ===== === ====
01 01/01/2010 14/01/2010 S
02 15/01/2010
BTW - If you don't have a unique id , against your dates you can do this is oracle..FYI
with date_ranges
as
(
SELECT
rownum as pkey,
date_ranges.*
FROM date_ranges
)
select
dr1.*
from
date_ranges dr1 , date_ranges dr2
where dr1.pkey > dr2.pkey
AND dr1.end_dt >= dr2.start_dt
AND dr2.end_dt >= dr1.start_dt
When I needed to compare two time spans in SQL for overlap, here are the four scenarios I could think of:
Here is the OR statement I created to capture these scenarios (in my case Oracle SQL):
and (
s1.start between s2.start and s2.end
OR
s1.end between s2.start and s2.end
OR
s2.start between s1.start and s1.end
)
In MySQL you basically need:
SELECT COUNT(*)
FROM date_ranges AS A, date_ranges AS B
WHERE A.id <> B.id
AND A.id > B.id
AND A.end_at > B.start_at
AND B.end_at > A.start_at
>
in the second and the third statement can be replaced with >=
to follow includes matching.
This topic is related to the "Allen's Interval Algebra" and there are some more reading on this can be found by those links:
Perhaps:
SELECT A.PKey, A.Start, A.End, A.Type
FROM calendar AS A, calendar AS B
WHERE (p.pkey<>a.pkey
AND b.start>=a.start
AND b.end<=a.end)
OR (b.pkey<>a.pkey
AND b.start<=a.start
AND b.end>=a.end)
We've all needed this kind of overlapping predicate in our queries for quite some time and I think I've found a really simple solution here.
In my application, as an example, I have policies that have the same Policy Number but maybe the Policy Description changes from one fiscal year to the next. When a user is entering a new record (same Policy Number, different Policy Description), I needed a way to tell if that policy already exists for the specified time range. If the new Policy Effective/Expiration dates overlap with whatever is already in the database, I needed to error out and tell the user why their input was not correct.
To do this, I went with the following predicate statement:
AND @_expiration >= EffectiveDate AND ExpirationDate >= @_effective
Hopefully someone else finds this as useful as I have.
I had to do a very similar thing for to stop duplicate holiday being entered into a table. it was in access and written to a temptable on input so had to query it in VBA SQL:
stCommandText = "SELECT " _
& "* " _
& "FROM " _
& "TableName a, " _
& "TableName b " _
& "WHERE " _
& "a.ID = b.ID " _
& "AND a.Startdate >= b.Startdate AND a.StartDate <= b.EndDate " _
& "AND a.AutoNo <> b.AutoNo "