如何在Rails中为关联模型添加唯一条件

时间:2012-11-13 14:51:22

标签: sql ruby-on-rails activerecord associations unique

我有一个简单的关系

Questionnaire has_many Answers

我有多份问卷。我想在不同的调查问卷中得到最新的5个答案。

如果我这样做:

Answer.find(:all, :order => "id desc" , :limit => 5)

我得到最后5个答案,但大部分时间所有5个答案都属于同一个问卷。如何查询来自不同问卷的最新答案

Answer.find(:all, :order => "id desc" , :limit => 5, :conditions => "DISTINCT questionnaire.id") ??

(想法是向管理员显示活动供稿,例如用户A在2012年11月11日回答问卷X中的答案,用户B在2012年11月1日回答问卷Y中的答案等。)

2 个答案:

答案 0 :(得分:2)

如果你正在使用Postgres我会做

Answer.find(:all,
  :order => "answers.attr1 asc, answers.attr2 asc, answers.attr3 asc, ..." , :limit => 5,
  :select => "DISTINCT ON (answers.questionnaire_id) answers.*")

请注意,您可能必须列出答案表中除了orders子句中的questionnaire_id之外的每一列,因此Postgres可以确切地知道您要选择什么,否则它可能是不明确的,您可能会收到SQL错误。

为了上帝的缘故升级到Rails 3!

Rails 3:

Answer.order("answers.attr1 asc, answers.attr2 asc, answers.attr3 asc, ...").
  limit(5).select("DISTINCT ON (answers.questionnaire_id) answers.*")

答案 1 :(得分:1)

使用GROUP BY获取每个问题的最新答案,并限制为最新的5:

latest_answer_ids = Answer.group(:questionnaire_id).
                           order('MAX(answers.id)').
                           limit(5).maximum(:id).values
latest_answers = Answer.where(:id => latest_answer_ids)

如果您需要将此作为一个查询执行,则可以使用Arel构建如下的子查询:

answers = Answer.arel_table
latest_answers = Answer.where(:id =>
           answers.
           group(:questionnaire_id).
           project('max(id)')
  ).order('id desc').limit(5)

这里的好处是子查询可以在任何DBMS中使用。