2015-02-07 56 views
1

在mysql中,如何检查两个日期范围是否重叠?如何检查两个日期范围是否在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}'))"; 

是否有这样做的更好的办法?

谢谢

+2

如果你不知道是之前或B之后,也没有AB是否能够完全嵌入小号挞末或反之亦然,那么我认为这是简单和简单的。 – GolezTrol 2015-02-07 23:25:35

+0

恩,时间是线性的,对吗?事件不能在它开始之前结束! – Strawberry 2015-02-07 23:37:28

+0

我没有说dateA和dateB是一个事件。他们只是两个日期,可以以任何顺序。 – omega 2015-02-08 01:07:42

回答

4

如果我们保证date_starteddatefinished$DateA$DateB不为NULL,并且我们保证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) 

我们可以轻易地否定,要返回“真”时,有“重叠”:

NOT (a > f OR b < s) 

转换,为SQL:

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

如果'最大'返回后面的日期,'最少'返回更早的日期,它不应该是'NOT(GREATEST('{$ dateA}','{$ dateB}') p.date_finished)'? – omega 2015-02-08 01:15:47

+0

@omega:是的,我把它们倒过来了。我编辑了我的答案。如果这四个值中的任何一个都可以为NULL,则可能需要修改该条件以说明该情况。 – spencer7593 2015-02-08 03:26:49

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

我dv。你对另一个答案的dv是错误的。 – Strawberry 2015-02-07 23:42:31

相关问题