获取最新的行,按属性的值分组

时间:2013-11-02 00:31:20

标签: sql ruby-on-rails activerecord

我正在编写一份问卷供用户填写。用户可以多次回答每个问题。回复有一个问题键,可以将它们与问题配对。我想获取用户当前响应的完整集合而不检索用户创建的每个响应。

响应表如下所示:

create_table "responses", :force => true do |t|
  t.string   "question_key", :null => false
  t.text     "value",        :null => false
  t.integer  "user_id",      :null => false
  t.datetime "created_at"
  t.datetime "updated_at"
end

以下是响应类的相关部分:

class Response < ActiveRecord::Base
  def self.current
    recent.uniq {|response| response.question_key}
  end

  scope :recent, order('created_at DESC')
end

user.responses.current获取了一组响应,但它似乎效率很低。它获取了用户创建的所有响应,然后丢弃了除question_key

的每个唯一值的最新响应之外的所有响应

我确实想出了一个SQL查询,它可以执行我想要的操作,在执行GROUP BY之前对行进行排序。有没有合理的方法在Response :: current中使用它?

SELECT *
FROM (
    SELECT *
    FROM responses
    WHERE user.id = 6
    ORDER BY created_at DESC ) as user_responses
GROUP BY question_key

2 个答案:

答案 0 :(得分:0)

您可以使用group方法在活动记录中执行分组。

Responses.where(user_id: '123').order('created_at DESC').group('question_key')

所以你的代码应该是这样的:

class Response < ActiveRecord::Base
  scope :recent, order('created_at DESC')
  def self.current
    recent.group('question_key')
  end
end

答案 1 :(得分:0)

此解决方案依赖于ID是连续的:

class Response < ActiveRecord::Base
  def self.current
    where(id: group(:question_key).maximum(:id).values)
  end
end

在获取用户的当前响应时会产生两个查询(user.responses.current),但它会避免返回所有用户的响应。

SELECT MAX(`responses`.`id`) AS maximum_id, question_key AS question_key FROM `responses` WHERE `responses`.`user_id` = 6 GROUP BY question_key
SELECT `responses`.* FROM `responses` WHERE `responses`.`user_id` = 6 AND `responses`.`id` IN (452, 447, 9, 225, 190, 230, 240)