我有YYYY-MM
格式的日期列表,我有一个包含starts_at
和ends_at
列的记录表。
我想查找传入列表中任何给定日期在starts_at
和ends_at
范围内的所有记录。
所以,给定2011-01, 2011-05, 2011-10
,我想:
| id | starts_at | ends_at | title |
| 3 | 2010-12-05 00:00:00 | 2011-02-02 00:00:00 | something cool |
| 4 | 2011-03-14 00:00:00 | 2011-05-01 00:00:00 | something else really cool |
| 5 | 2011-10-31 00:00:00 | 2012-12-23 00:00:00 | argh! end of the world! not cool! |
...虽然这些记录将被省略:
| id | starts_at | ends_at | title |
| 6 | 2010-10-05 00:00:00 | 2010-12-02 00:00:00 | something uncool |
| 7 | 2011-03-14 00:00:00 | 2011-04-31 00:00:00 | something else really uncool |
| 8 | 2011-12-23 00:00:00 | 2013-01-01 00:00:00 | yay! we're still alive! cool! |
如何在SQL中编写此WHERE
条件?
澄清:我正在寻找纯SQL的解决方案(我正在使用存储过程,因此通过PHP之类的其他语言进行动态注入实际上是不可能的,到目前为止我知道),日期列表作为string
(HTML表单输入)传递给查询。如果我能在SQL中以编程方式执行此操作,我很乐意将其分解为顺序BETWEEN
语句,但我不知道如何做到这一点。
基本上,我需要一种在纯SQL中表达以下逻辑的方法:
$months = explode(',', '2011-01,2011-05,2011-10');
$q = "SELECT records.* FROM records WHERE";
foreach($months as $month) {
$q .= " '$month' BETWEEN records.starts_at AND records.ends_at OR";
}
$q = substr($q, 0, -3) . ';';
答案 0 :(得分:2)
SELECT id, starts_at, ends_at, title
FROM yourtable
WHERE '2011-01-01' BETWEEN starts_at AND ends_at
OR '2011-05-01' BETWEEN starts_at AND ends_at
OR '2011-10-01' BETWEEN starts_at AND ends_at
答案 1 :(得分:0)
您可以将月份说明符翻译为月初和月末(som
和eom
)并自行完成:
SET sql_mode='ansi';
SELECT neezer.*
FROM neezer
JOIN (SELECT m || '-01' AS som,
DATE_SUB(DATE_ADD(m || '-01', INTERVAL 1 MONTH), INTERVAL 1 SECOND) AS eom
FROM (SELECT '2011-01' AS m
UNION ALL
SELECT '2011-05'
UNION ALL
SELECT '2011-10') d) month_intervals
ON som <= ends_at AND eom >= starts_at;
因此,我们将每个'2011-01'
转换为配对的DATE和DATETIME,然后计算重叠。 (我们将eom
转换为'YYYY-MM-DD 23:59:59'的原因是'2011-01'
匹配starts_at
'2011-01-01 01:00: 00'(否则eom
将在第一天被强制到00:00:00,与我们的starts_at
不匹配。