我有一个员工mysql数据库表,其中包含员工姓名和开始日期。我希望能够计算从今天起每个员工即将到来的3周年纪念日。 (例如,乔丹的下一个即将到来的周年纪念日将是08/25/2019,李的将是09/22/2017,迈克的10/26/2018)
id name startDate
---------------------------
0 Jordan 08/25/2010
1 Lee 09/22/2014
2 Mike 10/26/2015
低效的强力解决方案是生成从startDate到当前日期的所有周年日期加上今天的日期之后的一个日期,然后选择它。
但必须有一个更高效的SQL查询,以根据今天的日期显示每位员工的下一个即将到来的周年纪念日。必须以某种方式使用DATEDIFF。
答案 0 :(得分:1)
EDITED
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小提示向您展示它使用测试用例: 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()
vs 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
。
这是我方法,斯宾塞和戈登的并排比较 http://www.sqlfiddle.com/#!9/cf276a/3
它显示的内容:
答案 1 :(得分:0)
嗯,我认为这有点麻烦,但你可以在一个声明中做到这一点。
我认为可行的逻辑是在数年内取得差异,并将近似为3年。然后将其添加到开始日期。如果这大于当前日期,那就是下一个开始日期。否则,再增加三年:
12/31/2017
答案 2 :(得分:0)
戈登回答的方法很好。我只是认为需要稍作修改。使用:
INTERVAL 0 +
代替INTERVAL 3 +
并使用
INTERVAL 3 +
代替INTERVAL 6 +
我不想惹恼戈登的回答。
以下是完全相同方法的演示,语法稍有不同,并且还会在将来添加对startdate
的检查,我们希望在startdate
添加3年(至得到第一个三周年纪念日。)
SELECT t.id
, t.name
, t.startdate
, CASE
WHEN t.startdate > DATE(NOW())
THEN t.startdate + INTERVAL 3 YEAR
WHEN t.startdate + INTERVAL FLOOR( TIMESTAMPDIFF(YEAR,t.startdate,NOW()) /3)*3 YEAR > DATE(NOW())
THEN t.startdate + INTERVAL FLOOR( TIMESTAMPDIFF(YEAR,t.startdate,NOW()) /3)*3 YEAR
ELSE t.startdate + INTERVAL FLOOR( TIMESTAMPDIFF(YEAR,t.startdate,NOW()) /3)*3 + 3 YEAR
END AS next_3yr_anniv
FROM mytable t
ORDER BY ...