如何检查 mysql 中的两个日期范围是否重叠?
How to check if two date ranges overlap in mysql?
在 mysql 中,如何检查两个日期范围是否重叠?
我有这个:
注意:我们有 p.date_started <= p.date_finished
但 dateA
可以等于 dateB
或小于 dateB
或大于 dateB
.
代码:
$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}'))";
有更好的方法吗?
谢谢
我想你还有一项额外的测试。如果两个范围在一端重叠,或者如果第一个范围完全落在第二个范围内,前两个陈述将涵盖。
然后您需要测试第二个范围是否完全包含在第一个范围内,其他任何内容都将包含在前两个测试中。为此,您只需要测试开始或结束。
因此,我认为这会奏效
$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_started
、datefinished
、$DateA
和$DateB
不为NULL,我们保证date_started
不为NULL大于 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
我们可以很容易地检测到什么时候没有 "overlap" 个范围:
( a > f OR b < s )
当 是 一个 "overlap":
时,我们可以很容易地将其否定为 return "true"
NOT ( a > f OR b < s )
将其转换为 SQL:
NOT ( GREATEST('{$dateA}','{$dateB}') < p.date_started
OR LEAST('{$dateA}','{$dateB}') > p.date_finished
)
检查重叠的逻辑
A -> B
代表一个范围,a -> b
代表另一个范围。
重叠场景 1
A B
*------------*
a b
*------------*
重叠场景 2
A B
*------------*
a b
*------------*
重叠场景 3
A B
*------------*
a b
*--------------------*
重叠场景 4 - 当 a 或 b 与 A 或 B 相同时
a == A || a == B || b == A || b == B
Different scenarios would get fulfilled by checking against does four
scenarios.
我们的逻辑应该检查所有场景。
(scenario 1 (+4) || scenario 2 (+4) || scenario 3 )
(a >= A && a <= B) || (b >= A && b <= B) || (a < A && b > B)
即使数据库中的 to-date 可能为空,您也可以涵盖所有日期重叠情况,如下所示:
SELECT * FROM `tableName` t
WHERE t.`startDate` <= $toDate
AND (t.`endDate` IS NULL OR t.`endDate` >= $startDate);
无论如何,这将 return 所有与新 start/end 日期重叠的记录。
在 mysql 中,如何检查两个日期范围是否重叠?
我有这个:
注意:我们有 p.date_started <= p.date_finished
但 dateA
可以等于 dateB
或小于 dateB
或大于 dateB
.
代码:
$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}'))";
有更好的方法吗?
谢谢
我想你还有一项额外的测试。如果两个范围在一端重叠,或者如果第一个范围完全落在第二个范围内,前两个陈述将涵盖。
然后您需要测试第二个范围是否完全包含在第一个范围内,其他任何内容都将包含在前两个测试中。为此,您只需要测试开始或结束。
因此,我认为这会奏效
$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_started
、datefinished
、$DateA
和$DateB
不为NULL,我们保证date_started
不为NULL大于 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
我们可以很容易地检测到什么时候没有 "overlap" 个范围:
( a > f OR b < s )
当 是 一个 "overlap":
时,我们可以很容易地将其否定为 return "true"NOT ( a > f OR b < s )
将其转换为 SQL:
NOT ( GREATEST('{$dateA}','{$dateB}') < p.date_started
OR LEAST('{$dateA}','{$dateB}') > p.date_finished
)
检查重叠的逻辑
A -> B
代表一个范围,a -> b
代表另一个范围。
重叠场景 1
A B
*------------*
a b
*------------*
重叠场景 2
A B
*------------*
a b
*------------*
重叠场景 3
A B
*------------*
a b
*--------------------*
重叠场景 4 - 当 a 或 b 与 A 或 B 相同时
a == A || a == B || b == A || b == B
Different scenarios would get fulfilled by checking against does four scenarios.
我们的逻辑应该检查所有场景。
(scenario 1 (+4) || scenario 2 (+4) || scenario 3 )
(a >= A && a <= B) || (b >= A && b <= B) || (a < A && b > B)
即使数据库中的 to-date 可能为空,您也可以涵盖所有日期重叠情况,如下所示:
SELECT * FROM `tableName` t
WHERE t.`startDate` <= $toDate
AND (t.`endDate` IS NULL OR t.`endDate` >= $startDate);
无论如何,这将 return 所有与新 start/end 日期重叠的记录。