2016-09-15 162 views
3

我有一個員工mysql數據庫表,其中包含員工姓名和開始日期。我希望能夠從今天的日期算出每位員工即將到來的3週年紀念。 (因此,例如,喬丹的下一個即將到來的週年紀念將是2019年8月25日,李某的將是2017年9月22日,小李的2018年10月26日)根據加入日期計算員工的下一個3年週年紀念

id name  startDate   
--------------------------- 
0  Jordan  08/25/2010   
1  Lee  09/22/2014   
2  Mike  10/26/2015   

低效蠻力解決辦法是將生成所有周年從startDate到當前日期的日期加上今天日期之後的一個日期,然後選擇它。

但是根據今天的日期,每個員工都有一個更高效的SQL查詢來顯示下一個即將到來的週年紀念。必須以某種方式使用DATEDIFF。

+1

@KamilG怎麼這樣?從今天起的下一個週年將不得不是08/25/2019。 – CodeCrack

+1

你想爲閏日聘用的員工做什麼? – pilcrow

+0

@CodeCrack閏日實際上是一個很好的問題,但我會假設你並不在乎這麼多。我的回答,我相信其他人會假設週年日期將在2/28而不是2/29。這裏是一個sqlfiddle,展示了mysql如何將多年的加入視爲閏日。 http://www.sqlfiddle.com/#!9/f35e91/5 – Matt

回答

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) = 0andif 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())表示獲得當前日期的年份,例如2016YEAR(startDate)獲得例如startDate的年份。 2013MOD()爲您提供了從分裂所以2/3 remainder 1

2016 - 2013 gives you 3 so remainder of 3/3 is 0 

下一年的情況下這是不是一個函數[不帶括號]餘定義的時間間隔類型,你可以使用一天,一年,一個月,等

date INTERVAL + 1 year = add 1 year to date 

另一個例子是

startDate INTERVAL + NumOfYearsDiff year = add NumOfYearsDiff to startDate 

在第二種情況下進行比較時,我做的是通過減去日期的年份整數使這兩個日期基本上是YEAR 0001,然後比較哪會告訴我哪個日期以便在今年晚些時候瞭解這個週年紀念日是否已經過去,或者今年還會繼續。 TIMESTAMPDIFF會自動爲您取得學位,但如果您使用,那麼週年日期將是下一個日期,例如2019如果是在2016。所以如果你想今天展示它,你仍然必須檢查我所做的相同條件,這意味着沒有真正的理由使用TIMESTAMPDIFF

這裏是我的方法,斯賓塞的側面比較sqlfiddle側,和戈登的 http://www.sqlfiddle.com/#!9/cf276a/3

顯示內容:

  • 如果今天紀念日是戈登的&斯賓塞的方法,會顯示下一個週年如今天+ 3年。哪些可能或不可能被期望?
  • 戈登的回答爲未來的日期將顯示起始日期代替的startDate +3年
+0

@CodeCrack讓我知道這是否適合你,如果你想要5週年紀念,10等等,只需用5或10替換3。 – Matt

+0

我建議用三個邊界情況來測試它。週年日期是昨天的日期(應該返回昨天+ 3年)。其中一個週年日是今天(不知道這裏是什麼運作)。還有一個明天是週年紀念日(應該回到明天)。 – MatBailie

+0

http://www.sqlfiddle.com/#!9/e2c3d/1顯示當週年紀念是「今年晚些時候」時,代碼仍然錯誤地增加了3年。 – MatBailie

0

嗯,我認爲這有點麻煩,但你可以在一個聲明中做到這一點。

我認爲將會發揮作用的邏輯是在幾年內取得差異,並向上舍入到最近的3年。然後將其添加到開始日期。如果這大於當前日期,那是下一個開始日期。否則,添加三個歲:

select t.*, 
     (case when startdate + interval 3 + 3 * floor((year(curdate()) - year(startdate))/3) year > curdate() 
      then startdate + interval 3 + 3 * floor((year(curdate()) - year(startdate))/3) year 
      else startdate + interval 6 + 3 * floor((year(curdate()) - year(startdate))/3) year 
from t; 
+0

這種方法比較接近,但我認爲這不適用於startdate'2013-09-30',因爲今天的日期是'2016-09- 16' 。從開始日期開始的下一個「三週年紀念日」將在14天,即2016-09-30。 – spencer7593

0

戈登答案的方法是一個很好的一個。我只是覺得稍作修改是必要的。使用方法:

INTERVAL 0 +代替INTERVAL 3 +

和到位的INTERVAL 6 +

使用

INTERVAL 3 +我不想與戈登的回答一塌糊塗。

下面是一個完全相同的方法演示,語法略有不同,並且在將來添加對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 ... 
相關問題