Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if two date ranges overlap in mysql?

Tags:

date

mysql

In mysql, how can I check if two date ranges overlap?

I have this:

Note: We have that p.date_started <= p.date_finished but dateA can be equal to dateB or smaller than dateB or bigger than dateB.

CODE:

    $query = "SELECT u.first_name, u.last_name, u.avatar_filename, p.id, p.user_id, p.address, p.topic, p.latitude, p.longitude, d.name AS department_name
              FROM user u
              JOIN placement p ON p.user_id=u.id
              JOIN department d ON d.id = u.department_id
              WHERE p.active=1 AND (('{$dateA}' BETWEEN p.date_started AND p.date_finished) OR 
                                    ('{$dateB}' BETWEEN p.date_started AND p.date_finished) OR
                                    (p.date_started BETWEEN '{$dateA}' AND '{$dateB}') OR
                                    (p.date_finished BETWEEN '{$dateA}' AND '{$dateB}'))";

Is there a better way of doing this?

Thanks

like image 628
omega Avatar asked Feb 07 '15 23:02

omega


People also ask

Do date ranges overlap?

Figure 5 – Date ranges do not overlap. It's amazingly simple but powerful! In the example file I created, every date range has an end date.

How do you calculate overlap time?

Overlap = min(A2, B2) - max(A1, B1) + 1. In other words, the overlap of two integer intervals is a difference between the minimum value of the two upper boundaries and the maximum value of the two lower boundaries, plus 1.

How do you know if two date ranges overlap in Excel?

With SUMPRODUCT we can check if each start date is less than any of the end dates in the table AND, if each end date is greater than any of the start dates in the table. If the dates on each row meets this criteria for more than one set of dates in the table, then we know there are overlapping dates.

How do you get rid of overlapping dates in SQL?

let's pick the big date SELECT ID, EMP_ID, [START DATE], MAX(END DATE) FROM (SELECT ID, EMP_ID, TEAM, [END DATE], MIN([START DATE]) [START DATE] FROM my_table GROUP BY ID, EMP_ID, END_DATE ) a GROUP BY ID, EMP_ID, [START DATE] -- Now we are done with similar end date and similar start date -- At this point I will write ...


3 Answers

If we are guaranteed that date_started, datefinished, $DateA and $DateB are not NULL, and we're guaranteed that date_started is not greater than date_finished...

`s` represents `date_started`
`f` represents `date_finished`
`a` represents the smaller of `$DateA` and `$DateB`
`b` represents the larger of `$DateA` and `$DateB`

Visually:

      s-----f       overlap
 -----+-----+-----  -------  
  a-b |     |        NO
  a---b     |        YES
  a-----b   |        YES
  a---------b        YES
  a-----------b      YES
      a---b |        YES
      a-----b        YES
      a-------b      YES
      | a-b |        YES
      | a---b        YES     
      | a-----b      YES     
      |     a-b      YES
      |     | a-b    NO

We can easily detect when there's no "overlap" of the ranges:

( a > f OR b < s )

And we can easily negate that to return "true" when there is an "overlap":

NOT ( a > f OR b < s )

Converting that to SQL:

NOT ( GREATEST('{$dateA}','{$dateB}') < p.date_started
      OR LEAST('{$dateA}','{$dateB}') > p.date_finished
    )
like image 168
spencer7593 Avatar answered Nov 12 '22 23:11

spencer7593


Logic that checks for overlap

A -> B represent one range and a -> b represent another range.

overlap scenario 1

A           B
*----------*
     a           b
     *----------*

overlap scenario 2

     A           B
     *----------*
a           b
*----------*

overlap scenario 3

     A           B
     *----------*
a                        b
*---------------------*

overlap scenario 4 - is when a or b is same as A or B

a == A || a == B || b == A || b == B  

Different scenarios would get fulfilled by checking against does four scenarios.

Our logic should check for all scenarios.

(scenario 1 (+4) || scenario 2 (+4)  || scenario 3 )

(a >= A && a <= B) || (b >= A && b <= B) || (a < A && b > B)
like image 21
DevWL Avatar answered Nov 12 '22 23:11

DevWL


You can cover all date overlapping cases even when to-date in database can possibly be null as follows:

SELECT * FROM `tableName` t
WHERE t.`startDate` <= $toDate
AND (t.`endDate` IS NULL OR t.`endDate` >= $startDate);

This will return all records that overlaps with the new start/end dates in anyway.

like image 39
Hussein Akar Avatar answered Nov 12 '22 21:11

Hussein Akar