2013-04-18 30 views
0

我得到了用戶的警報表,其中我們將警報發送到用戶在用戶定義的時間間隔像0(僅一次),3個月,6個月,1年MySQL的DATE_ADD和重複永遠

所以我設計了一個表像這樣

id | user_id | alert_date   | repeat_int 
-----+--------------+-------------------------+------------- 
12 | 747  | 2013-04-19 00:00:00 | 0 
13 | 746  | 2013-03-19 00:00:00 | 1 
14 | 745  | 2012-04-19 00:00:00 | 0 
15 | 744  | 2013-04-19 00:00:00 | 0 
16 | 743  | 2013-05-19 00:00:00 | 0 

我們發送警報之前一日之寒「alert_date」

用下面的查詢,我可以獲取數據

SELECT al.id, 
     al.user_id, 
     al.alert_date, 
     al.repeat_int AS repunit 
FROM alerts AS al 
WHERE DATE_ADD(alert_date,INTERVAL repeat_int MONTH)=date_add(CURRENT_DATE,INTERVAL 1 DAY) 
    OR date(al.alert_date)=date_add(CURRENT_DATE,INTERVAL 1 DAY) 

其工作的文件,但我真正的問題是

的重複只會使用一次,我們需要它重複每間隔

即。如果提醒日期爲2012-03-14,並且repeat_int爲0 - 只需要工作一次 但如果提醒日期爲2012-03-14且repeat_int爲1 - 需要從2012-03-14開始每14天工作一次2012-03-14

,如果提醒日期是2012-03-14,repeat_int是3 - 需要每三個月工作一次14.即2012-03-14,2012-06-14,2012-09-14等提醒...

是否有任何想法/方法來做到這一點? 在此先感謝

+1

應在二月底發生什麼,如果alert_date是2013年1月31日和repeat_int它1? – pilcrow

+0

然後它會是2013-02-28。查詢返回像這樣..它確定..但任何想法在所有月份重複永遠? – ramesh

+0

一旦確定它已發出警報,您是否更新了alert_date?因爲在這種情況下,查詢會更容易,否則它會更復雜? – Edper

回答

2

更新

的OP已經改變了自己的模式在迴應評論,所以查詢基本上是:

SELECT * 
    FROM alerts 
WHERE CURRENT_DATE + INTERVAL 1 DAY = COALESCE(next_alert_date, alert_date); 

該處理的第一個運行「next_alert_date」爲NULL。

原來的答覆

對於原始模式:

SELECT * 
    FROM alerts 
    JOIN (SELECT CURRENT_DATE + INTERVAL 1 DAY AS tomorrow) d 
WHERE -- We want to alert if 
     -- 1. Tomorrow is the alert_date 
     tomorrow = alert_date 
     OR 
     -- 
     -- 2. Tomorrow is "repeat_int" months removed from alert_date, falling on 
     --  the same day of the month or on the end of the month if the original 
     --  alert_date day of month is later in the month than is possible for us 
     --  now. E.g., 2013-01-31 repeated monthly is adjusted to 2013-02-28. 
     (
     PERIOD_DIFF(DATE_FORMAT(tomorrow, '%Y%m'), DATE_FORMAT(alert_date, '%Y%m')) 
      MOD repeat_int = 0 
     AND 
     -- Make sure we are at the same day of the month 
     ((DAYOFMONTH(tomorrow) = DAYOFMONTH(alert_date) 
      OR 
     -- Or, if the day of the alert is beyond the last day of our month, 
     -- that we are at the end of our month. 
      (LAST_DAY(alert_date) > LAST_DAY(tomorrow) 
       AND 
      DAYOFMONTH(tomorrow) = LAST_DAY(tomorrow))) 
     );