2013-07-01 89 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日之后提醒是否需要在月的最后一天或如果没有那么多天等,则添加选项。 –