Archive for April 25th, 2009
Selecting timestamps for a time zone
Comments enabled. I *really* need your comment
From Stack Overflow:
How can I reuse a computed column in an SQL query in MySQL?
My query is something like this:
SELECT CONVERT_TZ(
IF(timestamp_start > last_update, timestamp_start, last_update),
'GMT',
user.timezone
) AS time_usr_tz
FROM schedule
JOIN user
ON schedule.user_id = user.user_id
WHERE CONVERT_TZ(
IF(timestamp_start > last_update, timestamp_start, last_update),
'GMT',
user.timezone
) < CURRENT_TIMESTAMP() [/sourcecode] As you can see, theCONVERT_TZ (…)
part is repeated.This is only a sample query. Actually, I have to use that computed column several times. So if I make change in one place, I have to change in many places. And the size of the query becomes scary, too.
Is there any way to avoid such duplication?
The duplication part is simple. We just need to wrap the query in a subquery or use HAVING
clause, like this:
SELECT * FROM ( SELECT CONVERT_TZ( IF(timestamp_start > last_update, timestamp_start, last_update), 'GMT', user.timezone ) AS time_usr_tz FROM schedule JOIN user ON schedule.user_id = user.user_id ) q WHERE time_usr_tz < CURRENT_TIMESTAMP()
, or this:
SELECT CONVERT_TZ( IF(timestamp_start > last_update, timestamp_start, last_update), 'GMT', user.timezone ) AS time_usr_tz FROM schedule JOIN user ON schedule.user_id = user.user_id HAVING time_usr_tz < CURRENT_TIMESTAMP()
But what I'd really like to write about today is the performance of such a query.
This query looks for the list of schedules and finds the schedules the were to be started by the time the query is issued.
The problem is that the schedule timestamps are not bound to any timezone, and should be converted to the user's timezone to find out if they're are due or not.
That can be seen as a design flaw, but in fact that can be exactly what a user needs. Say, a user wants to be woken up every day at 9:00 and reminded to take a pill at 13:00, but if she goes from Washington, D.C. to Honolulu, she may want all her alarm clocks to change from EST to HST. Instead of updating all the timestamps it's of course easier to update a single field in her profile.
The query uses columns from both tables inside a function in the WHERE
condition, that's why no indexes can be used to filter the timestamps.
If schedule
is large enough, this can be a problem for a busy service.
Now, let's create the sample tables and see what can be done. For the sake of simplicity, we'll leave only timestamp_start
column in the schedules
, which is enough to illustrate the point.
Read the rest of this entry »