0

私は以下のようなモデル構造を持っています:

  1. ユーザーは、ResponseSets を介して多くの調査を行っています (ユーザーは、試行ごとに ResponseSets を作成することにより、同じ調査に複数回参加できます)。
  2. ResponseSet には多くの Response があります
  3. 応答は、質問、回答、および応答セットに属します。

次を見つけるにはレールクエリが必要です:

  1. 回答に対応する特定の調査の最後の ResponseSet (最後の試行を意味します) で特定の回答を選択したユーザーの数。

  2. 質問に対応する特定のアンケートの最後の ResponseSet (最後の試行を意味します) で特定の質問を選択したユーザーの数。

4

2 に答える 2

2

PostgreSQL を使用しているため、サブクエリ内でウィンドウ関数を使用してロジックを簡素化することをお勧めします。サブクエリは、指定されたクエリのすべての response_sets を収集します。外側のクエリは、(ウィンドウ関数によって生成された rowNum に基づいて) その調査のユーザーごとの最後の ResponseSet にフィルターをかけ、指定された回答に関連付けられた応答が含まれていることを確認します。

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 ごとに 1 回しか使用できないことを前提としていることに注意してください。そうでない場合は、次のように置き換え.countて、これをさらに絞り込むことができます。.count(:distinct => :user_id)

于 2013-05-27T19:44:07.420 に答える
1

コメントで述べたようにWITH、最新の応答を見つけるには、サブクエリまたは Postgresql 句が必要です。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 に答える