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

时间:2014-11-05 19:39:04

标签: ruby-on-rails ruby postgresql activerecord 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

这让我走了一半,我当然可以遍历这些行并获取每个用户的第一行。但这对我来说真是太糟糕了,因为我正在使用Ruby中的Arrays做很多事情。

我也可以这样做:

Card.select('user_id, max(created_at)').group('user_id')
# => gives me user_id and created_at

...但我只收回user_ids和created_at时间戳。我不能选择任何其他列(包括id),所以我回来的东西毫无价值。我也不明白为什么PG不会让我选择比上面更多的列而不将它们放在group_by或聚合函数中。

我更愿意只使用ActiveRecord找到一种方法来获得我想要的东西。我也愿意在原始SQL中编写此查询,但如果我无法通过AR完成此操作。顺便说一句,我使用的是Postgres数据库,这限制了我的一些选择。

谢谢你们。

2 个答案:

答案 0 :(得分:3)

我们自己加入卡片表,开启

a)first.id != second.id
b)first.user_id = second.user_id
c)first.created_at < second.created_at

Card.joins("LEFT JOIN cards AS c ON cards.id != c.id AND c.user_id = cards.user_id AND cards.created_at < c.created_at").where('c.id IS NULL')

答案 1 :(得分:-1)

我发现一个解决方案在性能方面不是最理想的,但是当时间很短或者是一个业余爱好项目时,它可以用于非常小的数据集:

Card.all.order(:user_id, :created_at).to_a.uniq(&:user_id)

这将获取AR:Relation结果,将它们转换为Ruby数组,然后使用Proc对结果执行Array #uniq。经过一些简短的测试后,看起来#uniq会保留顺序,所以只要在使用uniq之前一切正常,你应该是好的。

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