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 个月后的日期进行比较。