2013-07-01 70 views
3

在我的一個Web應用程序(PHP和MySQL)中有一個用戶事件提醒。用戶可以添加下一個提醒日期,也可以設置重複間隔(即僅限一次,3個月,6個月和每年)。保存了具有價值的MySQL日期重複

0 - One time event 
3 - Every 3 months 
6 - Every 6 months 
12 - Yearly 

表像

id  | emp_id  | alert_date   | repeat_interval 
--------+----------------+-----------------------+---------------------- 
1  |  124  | 2014-05-02 00:00:00 |  3 
--------+----------------+-----------------------+---------------------- 
2  |  123  | 2014-05-02 00:00:00 |  12 
--------+----------------+-----------------------+---------------------- 
3  |  122  | 2014-02-02 00:00:00 |  6 
--------+----------------+-----------------------+---------------------- 
4  |  121  | 2014-07-02 00:00:00 |  0 
--------+----------------+-----------------------+---------------------- 
5  |  124  | 2014-05-02 00:00:00 |  6 
--------+----------------+-----------------------+---------------------- 
6  |  125  | 2014-08-02 00:00:00 |  6 
--------+----------------+-----------------------+---------------------- 
7  |  126  | 2014-06-02 00:00:00 |  12 
--------+----------------+-----------------------+---------------------- 
8  |  127  | 2014-05-02 00:00:00 |  3 
------------------------------------------------------------------------ 

的REPEAT_INTERVAL現在我每天早上有一個「的cronjob」跑,尋找事件和警報發送給用戶。我有以下的MySQL查詢

SELECT * 
FROM alerts as al 
WHERE date(al.alert_date) = DATE_ADD(CURRENT_DATE, INTERVAL 1 DAY); 

這將返回tmrw的警報,我可以用這個郵件發送。但我的問題是如何也採取這些間隔?

即如果alert_date是2013年1月5日,並設置重複3個月,然後需要在 2013年1月5日發送郵件和3個月

的間隔其實這是這樣做的正確方法目的?或者我需要改變表格?

任何人都可以給我一個想法嗎? 在此先感謝

+1

請更具體。您是否希望從'alert_date'或'alert_date'發送一封'每天3個月'的電子郵件,然後在'alert_date'後3個月再發一封電子郵件。 – RiggsFolly

+0

由於該列名稱爲repeat_ * interval *,因此我認爲可以安全地假設這是一個重複發生。 – Eric

回答

2

喲可以更新alert_date與下一個日期,它應該提醒。 因此,每次執行cronjob時,都會使用alert_date + repeat_interval月數更新所有具有repeat_interval!= 0的警報。我想你可以使用DATE_ADD()函數只是ATT月:

UPDATE alerts SET alert_date = DATE_ADD(alert_date, INTERVAL repeat_interval MONTHS) WHERE repeat_interval != 0 

如果你需要存儲原來的日期,只需要創建一個額外的列,next_alert,和更新日期等。

1

您可以添加更多的列next_alert_date將存儲下一個日期上的警報將列值按設定的時間間隔來發送和升級到下一個警報日期,你也可以使用相同的cron吧。再添加一列可以幫助您跟蹤它的啓動時間,也就是您當前的alert_date列。

2

我建議你在你的數據庫中添加另一列(例如next_alert),這會在下一個事件發生時告訴你。

然後在你的cron腳本,你只檢查next_alert日期匹配當前的日期,如果是,調整next_alertnext_alert + repeat_interval當然可以用特定的SQL函數添加月迄今

DATE_ADD(next_alert, INTERVAL repeat_interval MONTHS) 

,或者使用PHP的方法做到這一點。

0

您不需要添加像next_alert或next_date等任何字段。您可以簡單地從下面的代碼中找到提醒。

只需創建一個函數並在該函數中傳遞日期。以下代碼將爲您提供該日期的結果。

CREATE TABLE `reminder` (
    `id` int(11) NOT NULL auto_increment, 
    `title` varchar(255) NOT NULL, 
    `startdate` datetime NOT NULL, 
    `enddate` date NOT NULL, 
    `kind` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

-- 
-- Dumping data for table `reminder` 
-- 

INSERT INTO `reminder` (`id`, `title`, `startdate`, `enddate`, `kind`) VALUES 
(1, 'This is reminder', '2015-06-03 19:25:44', '2015-07-21', 'weekly'); 

-- Query data get results for 2015-06-17 from `reminder` table 
SELECT CONCAT_WS(' ','2015-06-17',TIME(startdate)) AS ReminderDateTime, title 
    FROM reminder 
    WHERE IF(
    kind='daily', 
    ((UNIX_TIMESTAMP('2015-06-17') -UNIX_TIMESTAMP(DATE(startdate))) % (1*24*60*60)=0) , 
    IF(
     kind='weekly', 
     ((UNIX_TIMESTAMP('2015-06-17') -UNIX_TIMESTAMP(DATE(startdate))) % (7*24*60*60)=0) , 
     IF(
     kind='monthly', 
     DAYOFMONTH('2015-06-17')=DAYOFMONTH(startdate),    
     IF(
      kind='quarterly', 
      ((UNIX_TIMESTAMP('2015-06-17') -UNIX_TIMESTAMP(DATE(startdate))) % (91*24*60*60)=0) , 
      IF(
      kind='yearly', 
      DAYOFYEAR('2015-06-17')=DAYOFYEAR(startdate), 
      IF(
       kind='', 
       startdate, 
       '0000-00-00 00:00:00' 
      ) 
     ) 
     ) 
    ) 
    ) 
    ) AND DATE(startdate) <='2015-06-17' AND IF(enddate<>'0000-00-00',enddate>='2015-06-17','1') ORDER BY ReminderDateTime ASC 
0

由僅限Ritesh修改了答案補充半年報,使每季度的任務重複在同一天,而不是91天和日期會在幾個季度會有所不同。

創建表

DROP TABLE IF EXISTS tbl_events; 
CREATE TABLE tbl_events ( 
    user int(11) NOT NULL, 
    id int(11) NOT NULL AUTO_INCREMENT, 
    title varchar(255) NOT NULL, 
    startdate datetime NOT NULL, 
    enddate date NOT NULL, 
    kind varchar(255) NOT NULL, 
    PRIMARY KEY (id) 
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; 

添加數據表

INSERT INTO tbl_events VALUES 
('1','1','This is daily reminder','2017-04-24 00:00:00','2020-12-31','daily'), 
('1','2','This is weekly reminder','2017-04-24 00:00:00','2020-12-31','weekly'), 
('1','3','This is monthly reminder','2017-04-24 00:00:00','2020-12-31','monthly'), 
('1','4','This is quarterly reminder','2017-04-24 00:00:00','2020-12-31','quarterly'), 
('1','5','This is yearly reminder','2017-04-24 00:00:00','2020-12-31','yearly'); 

查詢數據得到結果2017年10月23日從tbl_events表

SELECT user, '2017-10-23' AS Date, title 
    FROM tbl_events  
    WHERE IF( 
kind='daily', 
    ((UNIX_TIMESTAMP('2017-10-23') -UNIX_TIMESTAMP(DATE(startdate))) % (1*24*60*60)=0) , 
    IF( 
     kind='weekly', 
     ((UNIX_TIMESTAMP('2017-10-23') -UNIX_TIMESTAMP(DATE(startdate))) % (7*24*60*60)=0) , 
     IF( 
     kind='monthly', 
     DAYOFMONTH('2017-10-23')=DAYOFMONTH(startdate), 
     IF( 
      kind='quarterly', 
      DAYOFMONTH('2017-10-23')=DAYOFMONTH(startdate) AND abs(MONTH('2017-10-24')-MONTH(startdate))%3=0, 
      IF( 
      kind='semiannual', 
      DAYOFMONTH('2017-10-23')=DAYOFMONTH(startdate) AND abs(MONTH('2017-10-24')-MONTH(startdate))%6=0, 
       IF( 
       kind='yearly', 
       DAYOFYEAR('2017-10-23')=DAYOFYEAR(startdate), 
       IF( 
        kind='', 
        startdate, 
        '0000-00-00 00:00:00' 
       ) 
      ) 
     ) 
     ) 
    ) 
    ) 
    ) AND DATE(startdate) <='2017-10-23' AND IF(enddate<>'0000-00-00',enddate>='2017-10-23','1') ORDER BY Date ASC 
+0

如果日期在每月,每季度和每半年提醒28日之後,也最好添加一個選項。因此,如果在28日之後提醒是否需要在月的最後一天或如果沒有那麼多天等,則添加選項。 –