如何使用activerecord获取最后N条记录?
Posted
技术标签:
【中文标题】如何使用activerecord获取最后N条记录?【英文标题】:How to get last N records with activerecord? 【发布时间】:2010-09-30 00:56:43 【问题描述】:查询:limit
,我会得到前N条记录。获取最后 N 条记录的最简单方法是什么?
【问题讨论】:
【参考方案1】:这是 Rails 3 方式
SomeModel.last(5) # last 5 records in ascending order
SomeModel.last(5).reverse # last 5 records in descending order
【讨论】:
用 Postgres 试试这个!我肯定第一次遇到了麻烦。在 SQL 中,除非您指定顺序,否则无法保证顺序,但 mysql 更宽容。 注意:这不是实现它的好方法,性能方面 - 至少不符合 Rails 3.1。 SomeModel.last(5) 将无限制地执行 select 语句,将 SomeModel 的所有记录作为数组返回给 Ruby,之后 Ruby 会挑选出最后 (5) 个元素。效率方面,目前,您希望使用限制 - 特别是如果您可能有很多元素。 它做的正是它应该做的:SELECT "items".* FROM "items" ORDER BY id DESC LIMIT 50
在 Rails 4 中,由 .last() 生成的查询也是 Nick 提到的最佳选择
这对于 Rails 4+ 是不正确的,因为 SomeModel.last(5).class
== Array
。正确的方法是 SomeModel.limit(5).order('id desc')
per Arthur Neves,结果为 SELECT \"somemodels\".* FROM \"somemodels\" ORDER BY id desc LIMIT 5
【参考方案2】:
更新答案 (2020)
你可以通过last方法简单地获取最后N条记录:
Record.last(N)
例子:
User.last(5)
按 id 降序返回 5 个用户。
已弃用(旧答案)
我认为像这样的活动记录查询会得到你想要的('Something' 是模型名称):
Something.find(:all, :order => "id desc", :limit => 5).reverse
编辑:如 cmets 中所述,另一种方式:
result = Something.find(:all, :order => "id desc", :limit => 5)
while !result.empty?
puts result.pop
end
【讨论】:
似乎没有必要对数据进行两次排序,我目前正在先获取计数并将其与偏移量一起使用 这是我正在考虑的另一种方法,但这似乎更有效,因为这是对数据库的 2 次查询而不是 1 次。我想我假设您需要在某些时候迭代数组点,所以你可以让ruby在那个时候对其进行排序。 (即records.reverse.each ..) 另外,您不能反转数组并使用 Array.pop 迭代数组而不是反转它。ruby-doc.org/core-1.8.7/classes/Array.html#M000280 对于 Rails 3,请参阅 Bongs 的回复。这种方式仍然有效,但不再是首选方式。 不推荐调用#find(:all)。而是直接调用#all。【参考方案3】:在 Rails 3.1 中执行此操作的新方法是 SomeModel.limit(5).order('id desc')
【讨论】:
这比last(5)
更好,因为它返回了进一步链接的范围。
我在 Rails 4 上使用 SomeModel.limit(100).reverse_order
(guides.rubyonrails.org/…) 是一样的。
@lulalala 提到的“进一步链接的范围”示例:如果您只需要一列,SomeModel.limit(5).order('id desc').pluck(:col)
将执行SELECT SomeModel.col FROM SomeModel ORDER BY id desc LIMIT 5
,这比抓取所有列并丢弃除一列之外的所有列更有效带有SomeModel.last(5).map(&:col)
的列是SELECT *
而不是SELECT col
(调用last 后不能采摘;lazy-eval 链以last 结束)。【参考方案4】:
适用于 Rails 5(可能还有 Rails 4)
不好:
Something.last(5)
因为:
Something.last(5).class
=> Array
所以:
Something.last(50000).count
可能会毁掉你的记忆或永远消失。
好方法:
Something.limit(5).order('id desc')
因为:
Something.limit(5).order('id desc').class
=> Image::ActiveRecord_Relation
Something.limit(5).order('id desc').to_sql
=> "SELECT \"somethings\".* FROM \"somethings\" ORDER BY id desc LIMIT 5"
后者是一个未评估的范围。您可以链接它,或通过.to_a
将其转换为数组。所以:
Something.limit(50000).order('id desc').count
... 需要一秒钟。
【讨论】:
实际上甚至是 Rails 3。 ;)【参考方案5】:对于 Rails 4 及以上版本:
如果你想要第一个最旧的条目
,你可以尝试这样的事情YourModel.order(id: :asc).limit(5).each do |d|
如果您想要最近的最新条目,您可以尝试类似的方法。..
YourModel.order(id: :desc).limit(5).each do |d|
【讨论】:
这看起来像是 Rails 4 的最新答案,而不是接受的答案。我认为最新的语法应该是这样的:YourModel.all.order(id: :desc).limit(5)
@user2041318 :感谢没有" "
的新语法
Order() 返回所有记录。无需链接YourModel.all.order()
,因为与YourModel.order()
相同【参考方案6】:
解决方案在这里:
SomeModel.last(5).reverse
由于 rails 是惰性的,它最终会使用如下 SQL 访问数据库:“SELECT table
.* FROM table
ORDER BY table
.id
DESC LIMIT 5”。
【讨论】:
这将加载SomeModel
的所有记录
更好的方法是 limit();这看起来效率不高。
@Developer 是绝对正确的。执行的 SQL 是:SELECT
table.* FROM
table` ORDER BY table
.id
DESC LIMIT 5` 它不执行全选【参考方案7】:
如果您需要对结果进行排序,请使用:
Model.order('name desc').limit(n) # n= number
如果您不需要任何排序,只需要保存在表中的记录,则使用:
Model.last(n) # n= any number
【讨论】:
【参考方案8】:在我的 rails (rails 4.2)
项目中,我使用
Model.last(10) # get the last 10 record order by id
它有效。
【讨论】:
【参考方案9】:试试吧:
Model.order("field_for_sort desc").limit(5)
【讨论】:
你应该解释为什么这个解决方案是可行的。【参考方案10】:我们可以在 rails 5.2 中使用 Model.last(5)
或 Model.limit(5).order(id: :desc)
【讨论】:
【参考方案11】:我发现这个查询更好/更快地使用我喜欢的“pluck”方法:
Challenge.limit(5).order('id desc')
这给出了一个 ActiveRecord 作为输出;所以你可以像这样使用 .pluck :
Challenge.limit(5).order('id desc').pluck(:id)
在使用最佳 SQL 代码的同时快速将 id 作为数组提供。
【讨论】:
Challenge.limit(5).order('id desc').ids
也可以:)【参考方案12】:
假设 N = 5,你的模型是 Message
,你可以这样做:
Message.order(id: :asc).from(Message.all.order(id: :desc).limit(5), :messages)
看sql:
SELECT "messages".* FROM (
SELECT "messages".* FROM "messages" ORDER BY "messages"."created_at" DESC LIMIT 5
) messages ORDER BY "messages"."created_at" ASC
关键是子选择。首先,我们需要定义我们想要的最后一条消息是什么,然后我们必须按升序对它们进行排序。
【讨论】:
【参考方案13】:如果您的模型中有一个默认范围指定 Rails 3 中的升序,您将需要使用重新排序而不是上面 Arthur Neves 指定的顺序:
Something.limit(5).reorder('id desc')
或
Something.reorder('id desc').limit(5)
【讨论】:
【参考方案14】:一个简单的答案是:
Model.limit(5).order(id: :desc)
这个解决方案有一个问题,因为id
不能成为记录何时创建的唯一确定者。
更可靠的解决方案是:
Model.order(created_at: :desc).limit(5)
正如其他人指出的那样,也可以使用Model.last(5)
。唯一的问题是它返回Array
,而不是Model::ActiveRecord_Relation
。
【讨论】:
【参考方案15】:在查询中添加 :order 参数
【讨论】:
以上是关于如何使用activerecord获取最后N条记录?的主要内容,如果未能解决你的问题,请参考以下文章
使用 ActiveRecord,有没有办法在 after_update 期间获取记录的旧值