ActiveRecord 返回每个用户的最新记录(唯一)

gre*_*egb 5 ruby postgresql activerecord ruby-on-rails ruby-on-rails-4

我有一个用户模型和一个卡模型。用户有很多卡,所以卡有一个属性user_id

我想为每个用户获取最新的单张卡。我已经能够做到这一点:

Card.all.order(:user_id, :created_at)
# => gives me all the Cards, sorted by user_id then by created_at
Run Code Online (Sandbox Code Playgroud)

这让我成功了一半,我当然可以迭代这些行并获取每个用户的第一个行。但这对我来说真的很糟糕,因为我会使用 Ruby 中的数组来做很多这样的事情。

我也可以这样做:

Card.select('user_id, max(created_at)').group('user_id')
# => gives me user_id and created_at
Run Code Online (Sandbox Code Playgroud)

...但我只取回 user_ids 和created_at 时间戳。我无法选择任何其他列(包括 id),因此我返回的内容毫无价值。我也不明白为什么 PG 不允许我选择比上面更多的列而不将它们放入 group_by 或聚合函数中。

我更愿意找到一种仅使用 ActiveRecord 来获取我想要的内容的方法。我也愿意用原始 SQL 编写此查询,但前提是我无法使用 AR 完成它。顺便说一句,我使用的是 Postgres DB,这限制了我的一些选择。

多谢你们。

gre*_*egb -2

我找到了一种性能不佳的解决方案,但适用于非常小的数据集,当时间​​很短或者它是一个业余爱好项目时:

Card.all.order(:user_id, :created_at).to_a.uniq(&:user_id)
Run Code Online (Sandbox Code Playgroud)

这将获取 AR:Relation 结果,将它们转换为 Ruby Array,然后使用 Proc 对结果执行 Array#uniq。经过一些简短的测试后,#uniq 似乎会保留顺序,因此只要在使用 uniq 之前一切都按顺序进行,就应该没问题。

该功能对时间敏感,所以我现在将使用它,但我将在 @Gene 的响应和链接之后查看原始 SQL 中的某些内容。