Php Mysql相对日期减法

Php Mysql相对日期减法,php,mysql,sql,select,join,Php,Mysql,Sql,Select,Join,我有下面两张桌子 # Event table id title start_date end_date ---------------------------------------------------------- 1 Foo 2013-05-06 20:30:00 2013-05-06 22:45:00 2 Bar 2013-06-03 07:40:00 2013-05-06 10:45:

我有下面两张桌子

# Event table
id    title         start_date              end_date
----------------------------------------------------------
1      Foo     2013-05-06 20:30:00     2013-05-06 22:45:00
2      Bar     2013-06-03 07:40:00     2013-05-06 10:45:00
3      Demo    2013-05-02 00:22:00     2013-05-06 03:45:00
4      Test    2013-07-09 10:56:00     2013-05-06 13:45:00

# Notification table
id   event_id         mail         time    type     sent
----------------------------------------------------------
1       1       123@example.com     15    minute     0
2       1       234@example.com     01    day        0
3       3       655@example.com     01    week       0
4       4       888@example.com     40    minute     0
5       4       999@example.com     42    minute     1
5       4       987@example.com     30    minute     0
cron作业每分钟都会执行一个PHP脚本,以检查是否应将通知发送到通知表中的电子邮件地址。时间值是应发送提醒的事件开始日期之前的相对时间

例如,当cron作业在2013-05-06 20:15:00运行时,应将电子邮件发送到电子邮件地址123@example.com。还应考虑发送标志。如果该值设置为0,则如果该值低于发送日期,则应发送所有通知。例如,当cron作业在2013-07-09 10:26:00运行时,应将邮件发送到987@example.com888@example.com


我的问题是,在mysql中,查询必须是什么样子才能获取通知以满足上面对实际(now())日期的要求?我试过了,但没有成功。非常感谢您的帮助。

据我所知,这个问题有两个方面。一种是将不同的单位转换为时间比较。另一个是确保只发出一个通知

第一个可以通过一个大的
case
语句来处理。第二种方法是检查时间间隔,而不是不等式:

. . .
from event e join
     notification n
     on e.id = n.event_id
where (case when n.type = 'minute'
            then now() - interval n.time minute <= e.start_date and
                 now() + interval 1 minute - interval time minute > e.start_date
            when n.type = 'day'
            then now() - interval n.time day <= e.start_date and
                 now() + interval 1 minute - interval time day > e.start_date
            when n.type = 'week'
            then now() - interval 7*n.time day <= e.start_date and
                 now() + interval 1 minute - interval 7*time day > e.start_date
            when n.type = 'month'
            then now() - interval n.time month <= e.start_date and
                 now() + interval 1 minute - interval time month > e.start_date
       end) > 0 and sent = 0;
。
从事件e加入
通知
在e.id=n.event\u id上
其中(n.type='minute'时的情况)
然后现在()-间隔n.时间分钟e.开始日期
当n.type='day'
然后现在()-间隔n.时间日e.开始日期
当n.type='week'
然后现在()-间隔7*n.时间日e.开始日期
当n.type='month'
然后现在()-间隔n.时间月e.开始日期
结束)>0,发送=0;

而且,正如Tom指出的,最好为每个通知设置一个sent标志,而不是取决于特定的时间。作业可能由于各种原因而延迟。

Gordon,您有一些语法错误。您可以多次使用date_sub,但也可以添加/减去间隔。另外,你还有几个额外的结束参数。另外,使用发送标志不是比使用日期范围更好吗?@Tom。谢谢你的编辑。至于你的第二点评论,我完全同意。取决于特定的时间范围,在大多数环境中可能是危险的。发送的falg在那里,但未在您的解决方案中使用。或者我遗漏了什么?您必须将now()-interval n.time month更改为now()+interval n.time month,因为now必须在开始日期之前。它是加法而不是减法。请接受我的编辑。很难说,但这是事实。将类型保留在通知表中是一个难看的DB设计,有什么更好的方法?你的评论真的没有帮助!!在查找表中保留所有类型并在通知表中保留其引用可以加快平衡时间的动态计算