SELECT 无论存储年份如何,日期都在 X 个月内
SELECT where date is within X months away regardless of stored year
我目前有一个查询正在获取 deadline
不到 3 个月后的记录。 deadline
存储为日期,但年份并不重要,因为该记录应该每年标记一次。
我的查询:
SELECT client_name
FROM client
WHERE MOD(DAYOFYEAR(deadline) - DAYOFYEAR(CURDATE()), +365) <= 90
AND DAYOFYEAR(deadline) > DAYOFYEAR(CURDATE())
如果我凭记忆写下语法错误,我深表歉意——但它确实有效。
它一直有效,直到 deadline
在第一季度并且当前日期在最后一个季度,然后它不再 return 记录。我该如何解决这个问题?
所以查询需要return截止日期在当前日期3个月内的记录。 deadline
日期中的年份应该被忽略,因为这可能是几年前的事,但重要的是 deadline
的日期和月份。
还是我存储的日期有问题?我应该每年更新这个吗?
谢谢
一种方法是使用这样的条件测试:
WHERE CONCAT(YEAR(NOW()),DATE_FORMAT(d.deadline,'-%m-%d'))
+ INTERVAL CONCAT(YEAR(NOW()),DATE_FORMAT(d.deadline,'-%m-%d'))<NOW() YEAR
< NOW() + INTERVAL 3 MONTH
我们可以稍微解压一下。在第一行,我们创建了一个 "next due" 截止日期,方法是采用当前年份,并附加 deadline
.
中的月份和日期值
但是有一个问题。其中一些 "next due" 截止日期已经过去了。因此,要处理该问题(当 3 个月 "wraps" 进入下一年),我们需要在 之前 的任何 "next due" 截止日期后增加一年当前日期。
现在,我们可以将其与 3 个月后的日期进行比较,以确定 "next due" 截止日期是否在接下来的 3 个月内。
有点复杂。
这里有一个SQLFiddle作为示范:http://sqlfiddle.com/#!2/c90e9/3.
为了测试,NOW()
不方便,因为它总是 return 今天的日期。因此,为了测试,我们将所有出现的 NOW()
替换为用户定义的变量 @now
,并将其设置为不同的日期,以便我们可以适当地进行测试。
这是我用于测试的 SQL 语句。第一个表达式是我们计划在 WHERE
子句中使用的条件测试。为了测试,我们想要 return 所有行,只看哪些行被 due_in_3mo
标记为 TRUE
(1
) 哪些行被标记为 FALSE
(0
).
SELECT 中的第二个表达式仅列出 "next due" 截止日期,与第一个表达式中使用的相同。
其余的表达式是不言自明的...我们还想显示我们要比较的未来 3 个月的日期,以及原始 "deadline" 日期值。
SELECT
CONCAT(YEAR(@now),DATE_FORMAT(d.deadline,'-%m-%d'))
+ INTERVAL CONCAT(YEAR(@now),DATE_FORMAT(d.deadline,'-%m-%d'))<@now YEAR
< @now + INTERVAL 3 MONTH
AS `due_in_3mo`
, CONCAT(YEAR(@now),DATE_FORMAT(d.deadline,'-%m-%d'))
+ INTERVAL CONCAT(YEAR(@now),DATE_FORMAT(d.deadline,'-%m-%d'))<@now YEAR
AS `next_due`
, d.id
, d.deadline + INTERVAL 0 DAY AS `deadline`
, @now + INTERVAL 3 MONTH AS `now+3mo`
, @now + INTERVAL 0 DAY AS `now`
FROM d d
CROSS
JOIN (SELECT @now := '2015-11-01') i
ORDER BY d.id
更改内联视图中分配给 @now
的值(别名为 i
)以使用其他日期值进行测试。
(你可能想用 DATE(NOW())
代替 NOW()
这样时间就不会混在一起,你可能想从中减去另一天,这真的取决于如何你想处理 deadline
的边缘情况,月和日 与当前日期相同。(即你想将其处理为 "in the past" 还是不是。)
方法总结:生成 "next due" 截止日期作为未来的 DATE 值,并与现在 3 个月后的日期进行比较。
我目前有一个查询正在获取 deadline
不到 3 个月后的记录。 deadline
存储为日期,但年份并不重要,因为该记录应该每年标记一次。
我的查询:
SELECT client_name
FROM client
WHERE MOD(DAYOFYEAR(deadline) - DAYOFYEAR(CURDATE()), +365) <= 90
AND DAYOFYEAR(deadline) > DAYOFYEAR(CURDATE())
如果我凭记忆写下语法错误,我深表歉意——但它确实有效。
它一直有效,直到 deadline
在第一季度并且当前日期在最后一个季度,然后它不再 return 记录。我该如何解决这个问题?
所以查询需要return截止日期在当前日期3个月内的记录。 deadline
日期中的年份应该被忽略,因为这可能是几年前的事,但重要的是 deadline
的日期和月份。
还是我存储的日期有问题?我应该每年更新这个吗?
谢谢
一种方法是使用这样的条件测试:
WHERE CONCAT(YEAR(NOW()),DATE_FORMAT(d.deadline,'-%m-%d'))
+ INTERVAL CONCAT(YEAR(NOW()),DATE_FORMAT(d.deadline,'-%m-%d'))<NOW() YEAR
< NOW() + INTERVAL 3 MONTH
我们可以稍微解压一下。在第一行,我们创建了一个 "next due" 截止日期,方法是采用当前年份,并附加 deadline
.
但是有一个问题。其中一些 "next due" 截止日期已经过去了。因此,要处理该问题(当 3 个月 "wraps" 进入下一年),我们需要在 之前 的任何 "next due" 截止日期后增加一年当前日期。
现在,我们可以将其与 3 个月后的日期进行比较,以确定 "next due" 截止日期是否在接下来的 3 个月内。
有点复杂。
这里有一个SQLFiddle作为示范:http://sqlfiddle.com/#!2/c90e9/3.
为了测试,NOW()
不方便,因为它总是 return 今天的日期。因此,为了测试,我们将所有出现的 NOW()
替换为用户定义的变量 @now
,并将其设置为不同的日期,以便我们可以适当地进行测试。
这是我用于测试的 SQL 语句。第一个表达式是我们计划在 WHERE
子句中使用的条件测试。为了测试,我们想要 return 所有行,只看哪些行被 due_in_3mo
标记为 TRUE
(1
) 哪些行被标记为 FALSE
(0
).
SELECT 中的第二个表达式仅列出 "next due" 截止日期,与第一个表达式中使用的相同。
其余的表达式是不言自明的...我们还想显示我们要比较的未来 3 个月的日期,以及原始 "deadline" 日期值。
SELECT
CONCAT(YEAR(@now),DATE_FORMAT(d.deadline,'-%m-%d'))
+ INTERVAL CONCAT(YEAR(@now),DATE_FORMAT(d.deadline,'-%m-%d'))<@now YEAR
< @now + INTERVAL 3 MONTH
AS `due_in_3mo`
, CONCAT(YEAR(@now),DATE_FORMAT(d.deadline,'-%m-%d'))
+ INTERVAL CONCAT(YEAR(@now),DATE_FORMAT(d.deadline,'-%m-%d'))<@now YEAR
AS `next_due`
, d.id
, d.deadline + INTERVAL 0 DAY AS `deadline`
, @now + INTERVAL 3 MONTH AS `now+3mo`
, @now + INTERVAL 0 DAY AS `now`
FROM d d
CROSS
JOIN (SELECT @now := '2015-11-01') i
ORDER BY d.id
更改内联视图中分配给 @now
的值(别名为 i
)以使用其他日期值进行测试。
(你可能想用 DATE(NOW())
代替 NOW()
这样时间就不会混在一起,你可能想从中减去另一天,这真的取决于如何你想处理 deadline
的边缘情况,月和日 与当前日期相同。(即你想将其处理为 "in the past" 还是不是。)
方法总结:生成 "next due" 截止日期作为未来的 DATE 值,并与现在 3 个月后的日期进行比较。