如何检查mysql中的两个日期范围是否重叠?
在mysql中,如何检查两个日期范围是否重叠 我有这个:如何检查mysql中的两个日期范围是否重叠?,mysql,date,Mysql,Date,在mysql中,如何检查两个日期范围是否重叠 我有这个: 注意:我们有p.date\u开始我想你还有一个额外的测试。如果两个范围在一端重叠,或者如果第一个范围完全位于第二个范围内,则前两个语句将涵盖这两个范围 然后,您需要测试第二个范围是否完全包含在第一个范围内,其他任何内容都将在前两个测试中涵盖。为此,您只需要测试开始或结束 因此,我认为这是可行的 $query = "SELECT u.first_name, u.last_name, u.avatar_filename, p.id
注意:我们有
p.date\u开始我想你还有一个额外的测试。如果两个范围在一端重叠,或者如果第一个范围完全位于第二个范围内,则前两个语句将涵盖这两个范围
然后,您需要测试第二个范围是否完全包含在第一个范围内,其他任何内容都将在前两个测试中涵盖。为此,您只需要测试开始或结束
因此,我认为这是可行的
$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}'))";
如果我们保证date\u start
,datefinished
,$DateA
和$DateB
不为空,并且我们保证date\u start
不大于date\u 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 )
(a>f或b
当存在“重叠”时,我们可以很容易地否定这一点以返回“真”:
非(a>f或b
将其转换为SQL:
NOT ( GREATEST('{$dateA}','{$dateB}') < p.date_started
OR LEAST('{$dateA}','{$dateB}') > p.date_finished
)
NOT(最大({$dateA},{$dateB}')p.date_完成
)
检查重叠的逻辑
A->B
表示一个范围,A->B
表示另一个范围
重叠场景1
AB
*----------*
ab
*----------*
重叠场景2
AB
*----------*
ab
*----------*
重叠场景3
AB
*----------*
ab
*---------------------*
重叠场景4-当a或b与a或b相同时
a == A || a == B || b == A || b == B
通过检查DO 4,可以实现不同的场景
情景
(scenario 1 (+4) || scenario 2 (+4) || scenario 3 )
(a >= A && a <= B) || (b >= A && b <= B) || (a < A && b > B)
我们的逻辑应该检查所有场景
(scenario 1 (+4) || scenario 2 (+4) || scenario 3 )
(a >= A && a <= B) || (b >= A && b <= B) || (a < A && b > B)
(场景1(+4)|场景2(+4)|场景3)
(a>=a&&a=a&&b)
您可以覆盖所有日期重叠的情况,即使数据库中的“截止日期”可能为空,如下所示:
SELECT * FROM `tableName` t
WHERE t.`startDate` <= $toDate
AND (t.`endDate` IS NULL OR t.`endDate` >= $startDate);
从`tableName`t中选择*
其中t.`startDate`=$startDate);
无论如何,这将返回所有与新开始/结束日期重叠的记录。如果您不知道A是在B之前还是之后,也不知道A-B是否可以完全嵌入开始/结束,或者反之亦然,那么我认为这是最简单的。嗯,时间是线性的,对吗?事件不能在开始之前结束!我没有说dateA和dateB是一个事件。它们只是两个可以任意顺序的日期。如果magest
返回较晚的日期而least
返回较早的日期,那么它不应该是不应该是(magest({$dateA},{$dateB}')p.date u finished)
?@omega:是的,我是倒过来的。我已经编辑了我的答案。如果这四个值中的任何一个可以为空,则可能需要修改该条件来说明这一点。它还缩短了5个字节:-)当date\u start
等于所检查范围的结束日期时,此答案也没有处理边缘情况。。。这是否是一种重叠?将或p.date_finished作为NULL
条件插入SQL是有意义的,只要NULL值表示无限未来的一个点。在推荐SQL构造时,我们需要注意这一假设。因为并不是每个日期列中的每个空值都表示它。@DATE_finished的HusseinAkar空值是一个“缺失条件”,只有当空值表示一个覆盖整个未来的时段时,才需要修复它(如您的答案所示)。然后我们可以合并一个条件。但我们需要小心地收集空值行的特定含义。它还可以表示不能重叠的时段,或者可以表示一年或一小时的默认值。我没有深入研究处理所有边缘案件的细节。这个答案集中在被问到的问题上。
SELECT * FROM `tableName` t
WHERE t.`startDate` <= $toDate
AND (t.`endDate` IS NULL OR t.`endDate` >= $startDate);