我有一个用户模型和一个卡片型号。用户拥有多张卡片,因此卡片具有属性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数据库,这限制了我的一些选择。
谢谢你们。
答案 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中的内容。