2012-09-11 21 views
0

我將行用戶存儲在我的數據庫中作爲行。我允許用戶輸入他們的時區,並將其存儲在數據庫中。php/mysql正確的方式來查詢時區敏感的行

我的應用程序會在他們指定的時間每天給他們發電子郵件。我將電子郵件交付作爲一行存儲在另一個數據庫表中。這將通過一個cron工作來實現。

我希望我的查詢能夠提取用戶記錄,其中該用戶的最新電子郵件至少1400分鐘(24小時前),並根據他們的時區通過指定的時間。

我有以下查詢,但我不知道如何解釋MySQL的時區和用戶的時區。有什麼建議麼?

SELECT u.id, u.email, u.timezone_offset, u.email_time, TIMESTAMPDIFF( 
MINUTE , CONCAT(DATE(MAX(e.created)) , ' ', u.email_time) , NOW()) AS min_since_last_email 
FROM Users u 
INNER JOIN Emails e ON e.user_id = u.id 
WHERE min_since_last_email > 1400 
GROUP BY u.id 

時區偏移量是從GMT的偏移量..所以它會像我這樣的「-5」。

+0

我可能會建議擺脫'min_since_last_email'並將其作爲時區偏移。然後只需查詢當時需要發送的所有內容。舉個例子,假設每個人都在下午2點出發。因此,在格林尼治標準時間下午4點(2pm + 2小時)查詢'WHERE tz = -2'並將電子郵件僅發送給這些用戶。 – Mike

+0

嗯,我想最終允許他們指定每天,每兩天,每三天的時間間隔等。 – David

+0

在這種情況下,您可以將'last_email_sent'作爲'DATE'和'email_every'作爲'INT'並且做'WHERE tz = -1 * timezone_offset AND DATEDIFF(NOW(),last_email_sent)> = email_every'。我認爲應該有效。我真的不喜歡在日期/時間裏使用'INT'。 – Mike

回答

0

將邏輯轉一下:在PHP中進行計算,將所有數據以UTC存儲在數據庫中。那麼這是一個簡單的提取。您可以在PHP中使用時區函數輕鬆完成此操作,並且可以爲每個用戶定製 - SQL語句是一種全局語句,對於每位用戶(如您所遇到的)進行自定義更爲棘手。

因此,「發送時間電子郵件」可能是UTC時間凌晨4點(這在數據庫中),但您顯示給用戶「晚上9點」。

您可能遇到的一個問題是夏令時 - 當時區翻轉進/退出夏令時時,您需要重新計算所有時間。然而,你目前的方法不允許這個反正...

0

你上次發送電子郵件的日期是你的日期,所以存儲。

隨着您發送越來越多的電子郵件,計算每個用戶的最大值將變得越來越昂貴。非規範化並將該日期時間的副本放入用戶記錄中。

然後,計算該日期的時間和用戶時區的偏移量。

select *, date_add(now(), interval timezone_offset hour) as email_expected_on 
from users 
where last_email_date <= date_add(now(), interval timezone_offset hour); 

注意,它也是重要的,你不適用一個公式來users.last_email_date,否則您將無法在該列使用索引。

相關問題