0

我有一个用户警报表,我们必须在用户定义的时间间隔内向用户发送警报,例如 0(仅一次)、3 个月、6 个月、1 年

所以我设计了一张这样的桌子

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)

它的工作文件,但我真正的问题是

重复只会工作一次,我们需要它重复每个间隔

IE。如果警报日期为 2012-03-14 且 repeat_int 为 0 - 只需工作一次,但如果警报日期为 2012-03-14 且 repeat_int 为 1 - 需要从 2012-03-14 起每隔 14 日工作一次

如果警报日期是 2012-03-14 并且 repeat_int 是 3 - 需要在每三个月的 14 日工作。即警报在 2012-03-14、2012-06-14、2012-09-14 等...

有什么想法/方法可以做到吗?提前致谢

4

1 回答 1

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)) )
        );
于 2013-04-18T05:41:54.297 回答