I am trying to have a go at the infamous repeating events on calendars using PHP/MySQL. I've finally found something that seems to work. I found my answer here but I'm having a little difficulty finishing it off.
My first table 'events'.
ID NAME
1 Sample Event
2 Another Event
My second table 'events_meta that stores the repeating data.
ID event_id meta_key meta_value
1 1 repeat_start 1336312800 /* May 7th 2012 */
2 1 repeat_interval_1 432000 /* 5 days */
With repeat_start being a date with no time as a unix timestamp, and repeat_interval an amount in seconds between intervals (432000 is 5 days).
I then have the following MySQL which I modified slightly from the above link. The timestamp used below (1299132000 which is 12th May 2012) is the current day with no time.
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
In the above MySQL, the following code deducts the repeat_start field (EM1.'meta_value'
) from the current date and then divides it by the repeat interval field (EM2.'meta_value'
).
ELSE ( 1336744800 - EM1.`meta_value` ) / EM2.`meta_value`
OR
TODAYS DATE - START DATE / 5 DAYS
So here's the maths:
1336744800 - 1336312800 = 432000
432000 / 432000 = 1
Now that works perfect. But if I change the current timestamp 5 days ahead to 1336312800 which is 17th Mat 2012, it looks a bit like this:
1336312800 - 1336312800 = 864000
86400 / 432000 = 2
Which doesn't work because it equals 2 and in the MySQL it needs to equal 1. So I guess my question is, how do I get the MySQL to recognise a whole number rather than having to do this?
...
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,....)
Hope I'm making sense and I hope it's just a simple maths thing or a function that MySQL has that will help :) Thanks for your help!
EDIT: THE ANSWER
Thanks to @eggypal below, I found my answer and of course it was simple!
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
It's not entirely clear what you want your query to do, but the jist of your question makes me lean toward suggesting that you look into modular arithmetic: in SQL, a % b
returns the remainder when a
is divided by b
- if there is no remainder (i.e. a % b = 0
), then a
must be an exact multiple of b
.
In your case, I think you're trying to find events where the time between the event start and some given literal is an exact multiple of the event interval: that is, (literal - event_start) % event_interval = 0
. If it's non-zero, the value is the time to the next occurrence after literal
(and, therefore, to determine whether that next occurrence occurs within some period of time, say a day, one would test to see if the remainder is less than such constant e.g. (literal - event_start) % event_interval < 86400
).
If this isn't what you're after, please clarify exactly what your query is trying to achieve.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With