我有一個表「用戶」列「date_of_birth」(DATE格式與日,月,年)。 在前端,我需要列出5個即將到來的生日。如何在Rails中創建「即將到來的生日」模塊?
花了年齡試圖找出邏輯..也瀏覽在谷歌沒有運氣每一個可能的文章..
任何建議,如何做到這一點的回報率?
謝謝!
我有一個表「用戶」列「date_of_birth」(DATE格式與日,月,年)。 在前端,我需要列出5個即將到來的生日。如何在Rails中創建「即將到來的生日」模塊?
花了年齡試圖找出邏輯..也瀏覽在谷歌沒有運氣每一個可能的文章..
任何建議,如何做到這一點的回報率?
謝謝!
幾個答案建議計算/存儲年的一天並對其進行排序,但當靠近年底並需要考慮生日中的人時,這本身並不會很好。明年初。
我想找一個解決方案,你可以計算每個人的下一個生日的完整日期(年,月,日),然後對其進行排序。您可以在Ruby代碼中執行此操作,也可以在數據庫中使用存儲過程。後者會更快,但會讓你的應用更難以在以後遷移到不同的數據庫平臺。
只需每天更新一次即將到來的生日的列表就可以了,這意味着您可以使用某種形式的緩存。因此,需要查詢/代碼的速度是不成問題的,而且這樣的事情應該可以正常工作,只要你緩存結果:
class User
def next_birthday
year = Date.today.year
mmdd = date_of_birth.strftime('%m%d')
year += 1 if mmdd < Date.today.strftime('%m%d')
mmdd = '0301' if mmdd == '0229' && !Date.parse("#{year}0101").leap?
return Date.parse("#{year}#{mmdd}")
end
end
users = User.find(:all, :select => 'id, date_of_birth').sort_by(&:next_birthday).first(5)
編輯:固定到閏年正常工作。
我會有一個before_save回調函數,用於計算並存儲數據庫中一年中的某天以及生日。
然後你有一個簡單的查詢來拉回接下來的5個生日。確保處理年底的邊界條件(我會檢查你是否在RoR中得到5個結果,然後在1月1日運行一個新的查詢以獲得一些額外的生日來彌補它到5)。
您可能需要緩存結果,以便在查詢不在公共頁面時繼續重新運行查詢。
我也認爲今年的日子將是一段路要走,但事實上,一年中的大部分時間都有所不同,這取決於它是否是閏年,這使得它很棘手。
更好的方法是將月份和日期存儲爲字符串:d.strftime('%m%d')。然後,您可以使用它作爲(可能)兩個查詢(假設新欄是「MONTHDAY」)
首先,
User.find(:all,
:condition => [:monthday > Date.now.strftime('%m%d')],
:select => "DISTINCT monthday",
:limit => 5)
如果你沒有得到5個結果,再次進行查詢,除使用「 0101「而不是日期計算並降低限制。
這會讓你得到一個monthday
字符串列表,然後你必須回到日期。
如果您想要用戶,請刪除:select
行。
Rich_s對before_save的評論是如何計算字符串 – 2009-06-29 02:16:03
如果您使用的是Oracle,您可以在不創建新列的情況下執行此操作。國際海事組織這是一種氣味來創建一個包含您已有數據的列。
這個SQL有點難看 - 我確定有一個更優雅的方法來做到這一點。通常在這些情況下,我會問我的DBA朋友的建議。
User.find(:all,
:conditions =>
"TO_NUMBER(TO_CHAR(dob, 'MMDD')) >= TO_NUMBER(TO_CHAR(SYSDATE, 'MMDD'))",
:order => "TO_NUMBER(TO_CHAR(dob, 'MMDD'))",
:limit => 5)
有些人認爲重複的列速度較快,但如果你有足夠的用戶數據速度是一個問題,您應該基準對沒有它的表中有TO_NUMBER(TO_CHAR(dob, 'MMDD'))
函數索引的重複列。
這是如何工作的當年的最後幾天與同一年剩餘5人的生日相比較少? – 2009-06-29 04:19:10
以下是我發現今天的生日:
User.find_by_sql("select * from users where date_format(date_of_birth, '%m%d') = date_format(now(), '%m%d')"
)
我每天運行一次。它從大約100,000行不到一秒鐘。 (它不妥善處理出生於2月29日的人)
由於這篇文章在我的Rails應用程序3,我使用:
u = User.where("strftime('%m%d', date_of_birth) = ?", Date.today.strftime('%m%d'))
更新:
要在PostgreSQL使用:
u = User.where("extract(month from date_of_birth) = ? AND extract(day from date_of_birth) = ?", Date.today.strftime('%m'), Date.today.strftime('%d'))
這是更好地使用SQL,使這個查詢:
next_month = (Date.today + 1.month).month # or use any other integer
users_having_birhtday_next_month =
User.where("EXTRACT(MONTH FROM date_of_birth) = ?", next_month)
注:EXTRACT - PostgreSQL的功能
如果你的數據庫是MySQL的,下面是可能更快:
scope :birthday_next_week, (lambda {
where('DayOfYear(date_of_birth) >= 7
And DayOfYear(date_of_birth) - DayOfYear(curdate()) Between 0 and 6) Or
(MOD(YEAR(curDate()),4) = 0) And MOD(YEAR(curDate()),100) != 0
And (DayOfYear(date_of_birth) + 366 - DayOfYear(curdate())) % 366 < 7) Or
(DayOfYear(date_of_birth) + 365 - DayOfYear(curdate())) % 365 < 7').
order('DATE_FORMAT(date_of_birth, "%m-%d") ASC')
})
編輯:改變使其在一週前的除夕/飛躍工作年份。
什麼是數據庫?如果答案是在那裏做,它會有所作爲 – 2009-06-29 00:38:13
Kathy - 我會說在RoR模型中做,並避免任何數據庫特定的SQL – RichH 2009-06-29 01:48:16