2009-09-05 70 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