0

我有一个模型结构如下:

  1. 用户通过 ResponseSets 进行了许多调查(用户可以通过为每次尝试创建 ResponseSets 多次参加相同的调查)。
  2. ResponseSet 有很多 Response
  3. Response 属于 Questions、Answers 和 ResponseSets。

我需要一个 Rails 查询来查找:

  1. 有多少用户在他们最后的 ResponseSet(意味着最后一次尝试)中为与答案对应的给定调查选择了给定答案。

  2. 有多少用户在他们最后的 ResponseSet(意味着最后一次尝试)中为与问题对应的给定调查选择了给定问题。

4

2 回答 2

2

由于您使用的是 PostgreSQL,我建议在子查询中使用窗口函数来简化逻辑。子查询将收集给定查询的所有 response_set。外部查询过滤到该调查的每个用户的最后一个 ResponseSet(基于窗口函数生成的 rowNum),并确保它包含与给定答案关联的响应:

select_sql <<-SELECT
  response_sets.*,
  ROW_NUMBER() OVER (PARTITION BY response_sets.user_id ORDER BY response_sets.id DESC) as rowNum
SELECT

subquery = survey.response_sets.select(select_sql).to_sql

ResponseSet.joins(:responses).from(Arel.sql("(#{subquery}) response_sets")).
            where(responses: {answer_id: answer.id}).
            where("rowNum = 1").count

请注意,这假设给定答案每个 ResponseSet 只能使用一次。如果不是这种情况,您可以通过将其替换.count.count(:distinct => :user_id)

于 2013-05-27T19:44:07.420 回答
1

正如我在评论中提到的,您需要一个子查询或 PostgresqlWITH子句来查找最新响应,如果有很多 ReponseSet,即使使用索引也会变得相当昂贵。

另一方面,如果您有一个仅包含最新响应的表,则可以使用直接的嵌套连接。如果我正确理解了您的架构,那么这些很接近:

User.count(:joins => { :survey => {:latest_response_set => { :response => :answer }}}, 
           :conditions => ['answers.id = ?', answer_id])

User.count(:joins => { :survey => {:latest_response_set => { :response => :question}}}, 
           :conditions => ['questions.id = ? and surveys.id = ?', question_id, survey_id])

after_save您可以使用回调更新最新的响应表。这是相对安全的,因为回调被包装在事务中。

于 2013-05-27T19:57:26.143 回答