3

In one of my web application ( in PHP and MySQL ) there is a event reminder for users. User can add the next reminder date and also put the repeat interval ( ie Only Once, 3 months, 6 months and yearly ). Saving that in table like

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
------------------------------------------------------------------------

The repeat_interval having the value as

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

Now I have a "cronjob" running every morning, searching for events and send alerts to users. I have the following MySQL query

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

This will return the tmrw's alerts and I can send mail with this. But my question is how to take these intervals also ?

ie if the alert_date is 01-05-2013 and set repeat for 3 months then need to send mail on 01-05-2013 and the intervals of 3 months

Actually is this the correct way for this purpose ? Or I need to alter the tables ?

Can any one give me an idea ? Thanks in advance

4

5 回答 5

3

你可以用它应该被提醒的下一个日期更新 alert_date。因此,每次执行 cronjob 时,更新所有具有 repeat_interval != 0 的警报,并使用 alert_date + repeat_interval 月数。我想你可以使用 DATE_ADD() 函数来只写几个月:

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

如果您需要存储原始日期,只需创建一个额外的列 next_alert,然后更新该日期。

于 2013-07-01T11:32:59.063 回答
2

我建议您在数据库中添加另一列(例如next_alert),它会告诉您下一个事件何时发生。

然后在您的 cron 脚本中,您将简单地检查日期是否next_alert与当前日期匹配,如果是,则调整next_alertnext_alert + repeat_interval当然使用特定的 sql 函数来添加日期

DATE_ADD(next_alert, INTERVAL repeat_interval MONTHS)

或使用 PHP 方法来实现。

于 2013-07-01T11:29:03.313 回答
1

您可以再添加一个列 next_alert_date ,它将存储发送警报的下一个日期,并根据设置的间隔将列值更新为下一个警报日期,您也可以使用相同的 cron。再添加一列将帮助您跟踪它的启动时间,这也是您拥有的当前 alert_date 列。

于 2013-07-01T11:28:55.737 回答
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
于 2015-07-05T15:11:08.297 回答
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'); 

查询数据从 tbl_events 表中获取 2017-10-23 的结果

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
于 2017-04-24T08:44:48.757 回答