如何使用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条记录?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Java从mongodb获取最后插入的N条记录?

和尚:如何获取最后N条记录?

和尚:如何获取最后N条记录?

使用 ActiveRecord,有没有办法在 after_update 期间获取记录的旧值

如何使用 Hibernate 从 Mysql 获取最后一条记录?

如何使用聚合函数在 MySQL 查询中获取分组记录的第一条和最后一条记录?