【问题标题】:Rails - retrieve distinct recordsRails - 检索不同的记录
【发布时间】:2013-12-11 04:34:11
【问题描述】:

我有以下has_many和belongs_to关系:

class Trophy < ActiveRecord::Base
  has_many :awards
end

class Award < ActiveRecord::Base
  belongs_to :trophy
end

Award 模型有一个user_id 字段和一个trophy_id 字段。

以奖杯为例,我想返回 5 个最近但不同的用户奖项。

我能做到:

def recent_awards
  trophy_awards = awards.recent.includes(:user)
  trophy_awards.uniq! {|a| a.user_id}
  trophy_awards[0...4]
end

但是,它效率不高,因为我要处理很多记录。

目前,我正在这样做:

def recent_awards
  trophy_awards = awards.limit(50).recent.includes(:user)
  trophy_awards.uniq! {|a| a.user_id}
  trophy_awards[0...4]
end

问题是,如果最后 48 个奖项颁发给同一个用户,它不会给我 5 个不同的用户奖项。

返回 5 个最新但不同的用户奖项的最佳方式是什么?

【问题讨论】:

标签: sql ruby-on-rails ruby-on-rails-3 postgresql distinct


【解决方案1】:
def recent_awards
  awards.limit(5).recent.includes(:user).uniq
end

http://apidock.com/rails/ActiveRecord/QueryMethods/uniq

【讨论】:

  • OP 已经试过了,说它从数据库中抓取了太多的记录。 OP 只想从查询本身中获取 5 条记录。
  • 也许有点迂腐,但我认为awards.includes(:user).recent.uniq.limit(5) 读起来更好一些...
  • 这不会根据奖励表中的 user_id 返回唯一的奖励记录...
  • 基于“对于奖杯的实例,我想返回 5 个最近但不同的用户奖项”,我没有意识到这是一个要求。使用where 将其限制为特定的 user_d 很容易,但如果您可以像user.trophy.limit(5).recent.includes(:user).uniq.awards 或其他东西那样构建它可能会更好......关于您的关系的详细信息不足以猜测,但它应该很漂亮容易改变。无论哪种方式,.uniq 都会检索不同的记录。
【解决方案2】:

试试这个:

Award.find_by_sql("SELECT *
  FROM awards a1 INNER JOIN (
    SELECT MAX(created_at) AS recent
    FROM awards
    GROUP BY user_id) a2
  ON (a1.created_at = a2.recent)
  ORDER BY a1.created_at DESC
  LIMIT 5;")

【讨论】:

  • 这给了我 postgres 语法错误...应该说我正在使用 postgres
  • @keruilin,我编辑了答案。为我的项目修改的这个版本对我有用,检查一下,如果我需要进行任何其他更改,请告诉我。
  • 好吧,它不应该抛出错误,但实际上我不确定它是否会给你最新的:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-03
  • 1970-01-01
  • 2011-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多