2011-12-06 47 views
3

我正在構建一個Rails 3.1項目,其中一個模型包含生日屬性。我一直試圖找到一個基本上查找具有特定範圍內的生日的所有用戶的查詢。問題是這部分應用程序並不關心出生年份,僅僅是月份和日期。不幸的是,谷歌在這方面沒有太多幫助。使用Rails 3.1查找年度日期ActiveRecord查詢

有誰知道如何查詢在某個日期範圍內生日屬性爲「有周年紀念」的所有記錄嗎?我希望這是有道理的!

回答

5

聽起來你正在尋找EXTRACT

M.where(%q{ 
    array[extract(month from d)::int, extract(day from d)::int] between array[?, ?] and array[?, ?] 
}, lower_month, lower_day, upper_month, upper_day) 

其中M是你的模型,bday是生日列,上下變量持有的月份和日期界限。你也可以使用INTERSECT

M.find_by_sql([%q{ 
    select * from ms where array[? ,?] <= array[extract(month from bday)::int, extract(day from bday)::int] 
    intersect 
    select * from ms where array[?, ?] >= array[extract(month from bday)::int, extract(day from bday)::int] 
}, lower_month, lower_day, upper_month, upper_day]) 

另一個版本將使用to_char

M.where(
    "to_char(bday, 'MM') || to_char(bday, 'DD') between ? and ?", 
    '%2.2d%2.2d' % [lower_month, lower_day], 
    '%2.2d%2.2d' % [upper_month, upper_day] 
) 

你可以得到一個大丑一堆CASE語句過於相同的結果(這樣你只考慮月份邊界處的月份),但交叉點(IMO)更乾淨,更易於閱讀。使用(PostgreSQL)數組允許您將月份/日期對彼此作爲單個單位而不是單獨進行比較。

+0

太好了。我只用一些記錄進行測試,以前的查詢似乎可行,但是現在我可以看到那個會給出不正確的結果。非常感謝!我不是SQL大師,所以我總是需要這方面的幫助。 – Andrew

+0

@Andrew:我最初犯了同樣的錯誤,你可能做了這樣的事情,我應該擅長這個東西:)推斷基於有限數據集的查詢充滿危險,這就是爲什麼我們檢查彼此的工作。 –

+1

這個工作是否會在幾個月內(例如10/31-11/4)?例如,當我運行10/31的查詢的第一部分時,它只會記錄第31次或之後發生的生日(即只有31天的月份,而不是11/1,11/2等)。所以即使我在這個時間範圍之間有生日,我的交叉點仍然保持「0」。另外,當我加載查詢時,我從Rails控制檯中得到'錯誤數量的參數(5代表2)'。 – JHo

0

sql中有各種日期函數。其中一些只是提取日/月(獨立於年份)。我很確定有一個只返回「今年的一天」(即1到365)(如果沒有你可以寫一個) - 在這種情況下,你可以使用它並抓住所有具有它們的行在你現在掌握的一個小範圍內進行一年中的一天。

+2

儘管可能最安全的是分別考慮月份和月份,但您可能會遇到'提取(doy from bday)'的閏年問題。 –

+0

太棒了。我結束了使用提取,並分別考慮月份和月份的日期,它的工作就像一個魅力! – Andrew

+0

@Andrew:你確定它像魅力一樣工作嗎?你只應該看看月份的月份數是否等於月份的上限或下限(我承認我在原來的嘗試中犯了這個錯誤)。 –