如何检查mysql中两个日期范围是否重叠?

时间:2015-02-07 23:20:05

标签: mysql date

在mysql中,如何检查两个日期范围是否重叠?

我有这个:

注意:我们有p.date_started <= p.date_finisheddateA可以等于dateB或小于dateB或大于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}'))";

有更好的方法吗?

由于

4 个答案:

答案 0 :(得分:5)

如果我们保证date_starteddatefinished$DateA$DateB不为空,我们保证date_started不大于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`

目视:

      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

我们可以很容易地检测到范围没有“重叠”的时间:

( a > f OR b < s )

“重叠”时,我们可以轻易否定返回“true”:

NOT ( a > f OR b < s )

将其转换为SQL:

NOT ( GREATEST('{$dateA}','{$dateB}') < p.date_started
      OR LEAST('{$dateA}','{$dateB}') > p.date_finished
    )

答案 1 :(得分:1)

即使数据库中的日期可能为null,您也可以覆盖所有日期重叠的情况,如下所示:

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

这将始终返回与新的开始/结束日期重叠的所有记录。

答案 2 :(得分:0)

检查重叠的逻辑

A -> B代表一个范围,a -> b代表另一个范围。

重叠场景1

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

重叠场景2

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

重叠场景3

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

重叠方案4-当a或b与A或B相同

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

通过检查四个是否可以满足不同的方案   场景。

我们的逻辑应该检查所有情况。

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

(a >= A && a <= B) || (b >= A && b <= B) || (a < A && b > B)

答案 3 :(得分:-1)

我认为你有一个额外的测试。如果两个范围在一端重叠,或者如果第一个范围完全落在第二个范围内,前两个语句将涵盖。

然后,您需要测试第一个范围是否完全包含在第一个范围内,前两个测试中将涵盖其他任何内容。为此,您只需要测试开始或结束。

因此,我认为这将有效

 $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}'))";