2009-09-05 31 views
4

我想從表中獲取最新的條目。如果我只是使用SQL,你可以做rails - activerecord ...獲取第一個結果

Select top 1 * from table ORDER BY EntryDate DESC 

我想知道是否有一個很好的活動記錄方式做到這一點。
我可以這樣做:

table.find(:order => 'EntryDate DESC').first 

但好像能吸引整個結果集,然後使用Ruby選擇的第一個結果。我希望ActiveRecord創建只能帶來一個結果的sql。

回答

9

你需要的東西,如:

Model.first(:order => 'EntryDate DESC') 

這是簡寫形式,

Model.find(:first, :order => 'EntryDate DESC') 

看一看的文檔firstfind爲細節。

0

可以只使用的find_by_sql http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002267

table.find_by_sql "Select top 1 * from table ORDER BY EntryDate DESC" 
+0

這實際上並不適用於mysql(最開始你必須使用'limit 1'而不是'top 1')。在我問這個問題之前,我真的開始使用它,因爲它似乎我認爲ActiveRecord應該爲這樣的操作提供一些本地語法支持。如果沒有,那就是我需要知道的:) – Daniel 2009-09-05 16:27:49

1

在這種情況下,Rails文檔似乎很主觀。需要注意的是。首先是一樣的發現(:第一,等等...)

來源:http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M002263

「查找第一個 - 這將返回所使用的選項相匹配的第一個記錄這些選項可以是。如果沒有記錄可以匹配,則返回nil,使用Model.find(:first,* args)或其快捷方式Model.first(* args)。「

挖掘到的ActiveRecord的代碼,在base.rb(截至2009年9月5日)的1533線,我們發現:

def find_initial(options) 
     options.update(:limit => 1) 
     find_every(options).first 
    end 

這就要求其具有以下定義find_every:

def find_every(options) 
     include_associations = merge_includes(scope(:find, :include), options[:include]) 

     if include_associations.any? && references_eager_loaded_tables?(options) 
     records = find_with_associations(options) 
     else 
     records = find_by_sql(construct_finder_sql(options)) 
     if include_associations.any? 
      preload_associations(records, include_associations) 
     end 
     end 

     records.each { |record| record.readonly! } if options[:readonly] 

     records 
    end 

因爲它正在執行一個records.each,所以我不確定這個限制是否僅僅限制了查詢運行後它返回的記錄數量,但它肯定是這樣(不需要我自己進一步挖掘)。似乎你應該使用原始SQL,如果你擔心這個性能會受到影響。

+2

:limit選項傳遞給SQL,因此將所有記錄加載到Rails並在那裏過濾都沒有性能影響。查看查詢的最簡單方法是在控制檯上執行查詢時查找development.log。 – 2009-09-05 16:46:39

+0

當我再次閱讀我的答案後,我發現:limit => 1選項可能會一直傳遞到正在構建的原始SQL中,但我沒有時間繼續研究並且不想通過對行爲做出不正確的斷言來賭博 – MattC 2009-09-05 17:02:27