我正在尝试使用PHP / MySQL来处理日历上臭名昭着的重复事件。我终于找到了似乎有用的东西。我找到了answer here,但是我有点困难。
我的第一张桌子'事件'。
ID NAME
1 Sample Event
2 Another Event
我的第二个表'events_meta存储重复数据。
ID event_id meta_key meta_value
1 1 repeat_start 1336312800 /* May 7th 2012 */
2 1 repeat_interval_1 432000 /* 5 days */
使用repeat_start作为unix时间戳没有时间的日期,而repeat_interval是间隔之间的秒数(432000是5天)。
然后我有以下MySQL,我从上面的链接稍微修改了一下。下面使用的时间戳(1299132000,即2012年5月12日)是当前没有时间的日期。
SELECT EV.*
FROM `events` EV
RIGHT JOIN `events_meta` EM1 ON EM1.`event_id` = EV.`id`
RIGHT JOIN `events_meta` EM2 ON EM2.`meta_key` = CONCAT( 'repeat_interval_', EM1.`id` )
WHERE EM1.meta_key = 'repeat_start'
AND (
( CASE ( 1336744800 - EM1.`meta_value` )
WHEN 0
THEN 1
ELSE ( 1336744800 - EM1.`meta_value` ) / EM2.`meta_value`
END
)
) = 1
在上面的MySQL中,以下代码从当前日期中扣除了repeat_start字段(EM1.'meta_value'
),然后将其除以重复间隔字段(EM2.'meta_value'
)。
ELSE ( 1336744800 - EM1.`meta_value` ) / EM2.`meta_value`
OR
TODAYS DATE - START DATE / 5 DAYS
所以这是数学:
1336744800 - 1336312800 = 432000
432000 / 432000 = 1
现在完美无缺。但如果我提前5天将当前时间戳更改为1336312800(即2012年第17期),它看起来有点像这样:
1336312800 - 1336312800 = 864000
86400 / 432000 = 2
哪个不起作用,因为它等于2而在MySQL中它需要等于1.所以我想我的问题是,如何让MySQL识别整数而不是必须这样做?
...
WHERE EM1.meta_key = 'repeat_start'
AND (
( CASE ( 1336744800 - EM1.`meta_value` )
WHEN 0
THEN 1
ELSE ( 1336744800 - EM1.`meta_value` ) / EM2.`meta_value`
END
)
) = IN (1,2,3,4,5,6,7,8,....)
希望我有意义,我希望它只是一个简单的数学事物或MySQL有帮助的功能:)感谢您的帮助!
编辑:答案
感谢下面的@eggypal,我找到了答案,当然很简单!
SELECT EV.*
FROM elvanto_calendars_events AS EV
RIGHT JOIN elvanto_calendars_events_meta AS EM1 ON EM1.`event_id` = EV.`id`
RIGHT JOIN elvanto_calendars_events_meta AS EM2 ON EM2.`meta_key` = CONCAT( 'repeat_interval_', EM1.`id` )
WHERE EM1.meta_key = 'repeat_start'
AND ( ( 1336744800 - EM1.`meta_value` ) % EM2.`meta_value`) = 0
答案 0 :(得分:10)
你想要查询做什么并不完全清楚,但是你的问题的主旨让我倾向于建议你研究模块化算法:在SQL中,a % b
返回<{1}}除以a
时余下 - 如果没有余数(即b
),那么a % b = 0
必须是精确多个 a
。
在你的情况下,我想你正试图找到事件开始和某个给定文字之间的时间是事件间隔的精确倍数的事件:即{{1} }。如果它不为零,则该值是b
之后的下一次出现的时间(因此,为了确定下一次出现是否发生在一段时间内,比如一天,人们会测试是否余数小于这样的常数,例如(literal - event_start) % event_interval = 0
)。
如果这不是您所追求的,请详细说明您的查询要尝试实现的目标。