SQL: Select * 其中开始和结束在两个日期内
SQL: Select * where start and end falls within two dates
我有一个 tasks
table 这样的:
+-------+-------------------+---------------------+---------------------+
| rowid | title | start_task | due_date |
+-------+-------------------+---------------------+---------------------+
| 1 | Paint Apartment | 2018-03-01 07:00:00 | 2018-03-16 15:00:00 |
+-------+-------------------+---------------------+---------------------+
| 2 | Meeting with John | 2018-03-10 10:00:00 | 2018-03-10 12:30:00 |
+-------+-------------------+---------------------+---------------------+
| 3 | Buy Milk | 2018-03-04 20:00:00 | NULL |
+-------+-------------------+---------------------+---------------------+
| 4 | Renew Rail Card | NULL | 2018-03-07 09:00:00 |
+-------+-------------------+---------------------+---------------------+
我想 select 一周 2018-03-05
到 2018-03-11
的所有内容,因此它应该打印第 1、2 和 4 行。
所以我的查询应该包括以下内容:
- 2018-03-05 和 2018-03-11 之间开始的所有内容
- 在 2018-03-05 和 2018-03-11 之间到期的一切
- start_task 和 due_date 期间在 2018-03-05 和 2018-03-11 之间的所有内容
我当前的 SQL 执行 1 和 2 并打印第 2 行和第 4 行:
SELECT * FROM `tasks` tasks where ((`start_task` >= '2018-03-05 00:00:00' and `start_task` <= '2018-03-11 23:59:59') OR (`due_date` >= '2018-03-05 00:00:00' and `due_date` <= '2018-03-11 23:59:59'))
所以您只是遗漏了开始日期 - 截止日期期间跨越您正在检查的那一周的任何内容?这应该可以解决问题:
SELECT
*
FROM
`tasks` tasks
WHERE
(
(`start_task` >= '2018-03-05 00:00:00' and `start_task` <= '2018-03-11 23:59:59')
OR (`due_date` >= '2018-03-05 00:00:00' and `due_date` <= '2018-03-11 23:59:59')
OR (`start_task` <= '2018-03-11 23:59:59' and `due_date` >= '2018-03-05 00:00:00')
)
如前所述,这也可以简化为单个测试:
SELECT
*
FROM
`tasks` tasks
WHERE
COALESCE(`start_task`, '2018-03-11 23:59:59') <= '2018-03-11 23:59:59'
AND COALESCE(`due_date`, '2018-03-05 00:00:00') >= '2018-03-05 00:00:00'
我认为这是 MySQL 的正确语法,如果不正确,我们深表歉意。请注意,这也意味着 NULL
开始日期和 NULL
截止日期将是通过的,而您可能希望它是失败的?
您正在检查两个间隔之间的 non-empty 交集(start_date
➔ due_date
和 3 月 5 日 ➔ 3 月 11 日)。
您可以使用:
select *
from `tasks` tasks
where (`start_task` is null or `start_task` <= '2018-03-11 23:59:59') -- start <= end
and (`due_date` is null or `due_date` >= '2018-03-05 00:00:00') -- end >= start
(假设null
start/end日期表示无限间隔)
记为:"each interval must start before the other ends".
为了更好地理解原因,想想反问题。
为了使两个间隔有一个空交点,您必须在 interval 1
开始之前让 interval 2
结束:
interval 1: --------(---)--------
interval 2: -(---)---------------
或interval 2
在interval 1
结束后开始:
interval 1: --------(---)--------
interval 2: ---------------(---)-
否定这两个条件的合取并应用德摩根得到non-empty相交的条件。
我有一个 tasks
table 这样的:
+-------+-------------------+---------------------+---------------------+
| rowid | title | start_task | due_date |
+-------+-------------------+---------------------+---------------------+
| 1 | Paint Apartment | 2018-03-01 07:00:00 | 2018-03-16 15:00:00 |
+-------+-------------------+---------------------+---------------------+
| 2 | Meeting with John | 2018-03-10 10:00:00 | 2018-03-10 12:30:00 |
+-------+-------------------+---------------------+---------------------+
| 3 | Buy Milk | 2018-03-04 20:00:00 | NULL |
+-------+-------------------+---------------------+---------------------+
| 4 | Renew Rail Card | NULL | 2018-03-07 09:00:00 |
+-------+-------------------+---------------------+---------------------+
我想 select 一周 2018-03-05
到 2018-03-11
的所有内容,因此它应该打印第 1、2 和 4 行。
所以我的查询应该包括以下内容:
- 2018-03-05 和 2018-03-11 之间开始的所有内容
- 在 2018-03-05 和 2018-03-11 之间到期的一切
- start_task 和 due_date 期间在 2018-03-05 和 2018-03-11 之间的所有内容
我当前的 SQL 执行 1 和 2 并打印第 2 行和第 4 行:
SELECT * FROM `tasks` tasks where ((`start_task` >= '2018-03-05 00:00:00' and `start_task` <= '2018-03-11 23:59:59') OR (`due_date` >= '2018-03-05 00:00:00' and `due_date` <= '2018-03-11 23:59:59'))
所以您只是遗漏了开始日期 - 截止日期期间跨越您正在检查的那一周的任何内容?这应该可以解决问题:
SELECT
*
FROM
`tasks` tasks
WHERE
(
(`start_task` >= '2018-03-05 00:00:00' and `start_task` <= '2018-03-11 23:59:59')
OR (`due_date` >= '2018-03-05 00:00:00' and `due_date` <= '2018-03-11 23:59:59')
OR (`start_task` <= '2018-03-11 23:59:59' and `due_date` >= '2018-03-05 00:00:00')
)
如前所述,这也可以简化为单个测试:
SELECT
*
FROM
`tasks` tasks
WHERE
COALESCE(`start_task`, '2018-03-11 23:59:59') <= '2018-03-11 23:59:59'
AND COALESCE(`due_date`, '2018-03-05 00:00:00') >= '2018-03-05 00:00:00'
我认为这是 MySQL 的正确语法,如果不正确,我们深表歉意。请注意,这也意味着 NULL
开始日期和 NULL
截止日期将是通过的,而您可能希望它是失败的?
您正在检查两个间隔之间的 non-empty 交集(start_date
➔ due_date
和 3 月 5 日 ➔ 3 月 11 日)。
您可以使用:
select *
from `tasks` tasks
where (`start_task` is null or `start_task` <= '2018-03-11 23:59:59') -- start <= end
and (`due_date` is null or `due_date` >= '2018-03-05 00:00:00') -- end >= start
(假设null
start/end日期表示无限间隔)
记为:"each interval must start before the other ends".
为了更好地理解原因,想想反问题。
为了使两个间隔有一个空交点,您必须在 interval 1
开始之前让 interval 2
结束:
interval 1: --------(---)--------
interval 2: -(---)---------------
或interval 2
在interval 1
结束后开始:
interval 1: --------(---)--------
interval 2: ---------------(---)-
否定这两个条件的合取并应用德摩根得到non-empty相交的条件。