已编辑
SELECT
*
,CASE
WHEN CURDATE() <= startDate THEN startDate + INTERVAL 3 year
WHEN MOD((YEAR(CURDATE()) - YEAR(startDate)),3) = 0
AND (CURDATE() - INTERVAL YEAR(CURDATE()) year)
<= (startDate - INTERVAL YEAR(startDate) year)
THEN startDate + INTERVAL (YEAR(CURDATE()) - YEAR(startDate)) year
ELSE startDate + INTERVAL (year(CURDATE()) - YEAR(startDate) + 3 - MOD(YEAR(CURDATE()) - YEAR(startDate),3)) year
END as "Next3YrAniversary"
FROM
TableName
SQL Fiddle 向您展示它如何处理测试用例:
http://www.sqlfiddle.com/#!9/cf276a/1
反正思路如下:
startDate is Today or in future if so just add 3 years
-
Remainder of (Yesrs Diff / 3) = 0 and if current month/day is <= month/day of startDate 如果今年是周年纪念日并且还没有发生,那么add number of years between current date and startDate to startDate。如果是 2016 并且周年纪念日在 2016 中,则表示方式略有不同,它将查看今年是否已经过周年纪念日。
- 否则添加到开始日期:
Number of years between Start Date & Now + 3 years - Remainder of (Years between Now and startDate / 3)
关于YEAR() 与year 的注释。你可以写 year() 或 YEAR() 我倾向于大写我的特定函数等,但 year() 函数只获取日期年份的 INT。所以YEAR(CURDATE()) 表示获取当前日期的年份,例如2016、YEAR(startDate) 获取 startDate 的年份,例如2013。 MOD() 给你一个除法的余数所以2 / 3 remainder 1
2016 - 2013 gives you 3 so remainder of 3/3 is 0
不是函数的小写年份 [不带括号] 定义了可以使用日、年、月等的 INTERVAL 类型。
date INTERVAL + 1 year = add 1 year to date
另一个例子是
startDate INTERVAL + NumOfYearsDiff year = add NumOfYearsDiff to startDate
在情况 2 比较时,我所做的是通过从日期中减去年份整数来使两个日期基本上为 YEAR 0001,然后比较哪个日期会告诉我哪个日期在今年晚些时候,以了解周年纪念日是否已经过去或者今年还在继续。 TIMESTAMPDIFF 在一定程度上会自动为您执行此操作,但如果您使用,那么周年日期将是下一个日期,例如2019 如果今天是 2016。所以如果你想像今天一样展示它,你仍然需要检查我所做的相同条件,这意味着没有真正的理由使用TIMESTAMPDIFF。
这里是 My Method、Spencer 和 Gordon 的 sqlfiddle 并排比较
http://www.sqlfiddle.com/#!9/cf276a/3
它显示了什么:
- 如果今天是周年纪念日,Gordon's & Spencer 的方法会将下一个周年纪念日显示为今天 + 3 年。哪些可以或不可以?
- Gordon 对未来日期的回答将显示 startDate 而不是 startDate + 3 年