2

特定の制約が与えられたすべての個々のユーザーに対して、最初に作成されたレコードと、最初に作成されたレコード除くすべてのレコードを返そうとしています。私のSQLは壊れていますが、私の人生ではどこで/なぜなのかわかりません。

オブジェクト モデル

関心のある 4 つのモデルがあります: User、Course、Question、および QuestionRecord です。

ユーザーが質問に回答するたびに、QuestionRecord が生成されます。QuestionRecord は、User、Course、および Question との多対 1 です。(カーディナリティは正しいですか? 各 QuestionRecord には、正確に 1 つの User、1 つの Course、および 1 つの Question への外部キーがあります)

ルビーの場合:

class QuestionRecord < ActiveRecord::Base

  belongs_to :user
  belongs_to :course
  belongs_to :question
…
end

望ましい結果 #1: 最初の記録

私が望むのは、コースと質問を指定して、ユーザーの最初の質問レコードを返すことです。別の言い方をすれば、ジェーンとビルが質問に 2 回回答し、ジョンは未回答で、ピートが 7 回回答した場合、ジェーン、ビル、とピート。

コードでこれを行うこともできますが、効率のために SQL で行う必要があります。

これは私が持っているものです:

SELECT qr.id 
FROM users u 
INNER JOIN question_records qr 
ON u.id = 
  (SELECT x.user_id 
   FROM question_records x 
   WHERE x.course_id = #{course.id} 
   AND x.question_id = #{question.id} 
   AND x.user_id = u.id 
   ORDER BY created_at ASC 
   LIMIT 1 )

このクエリは 40 分ほど実行されるだけで、実際には何も返されません。50 レコードのサブセットで実行したところ、返されたすべての qr.id 結果が「1」であるという奇妙な問題がありました。

望ましい結果 #2:最初のレコードを除くすべて

ここで、最初のレコードを除くすべてのユーザーのすべてのレコードが必要です。私の考えでは、本質的に、これは同じクエリですが、すべてのレコードが必要であり、返されたインデックスを 1 つオフセットしたいという点が異なります。

SELECT qr.id 
FROM users u 
INNER JOIN question_records qr 
ON u.id = 
  (SELECT x.user_id 
   FROM question_records x 
   WHERE x.course_id = #{course.id} 
   AND x.question_id = #{question.id} 
   AND x.user_id = u.id 
   ORDER BY created_at ASC 
   OFFSET 1 )

ただし、最初のクエリが機能しない場合、2 番目のクエリも機能しないことは明らかです。

コーダ

このクエリに関するガイダンスはありますか? できるだけ効率的にするといいので、[course_id、question_id] などで question_records にインデックスを付けることができます。また、「GROUP BY x.user_id」を使用する可能性がないと仮定していますが、作品にガムを追加せずに追加する方法がわかりませんでした。

ちなみに、使用しているデータベースは MySQL です。

4

2 に答える 2

0

#1について、ID値が連続して発行される場合:

SELECT     MIN(qr.id) AS FirstQRID
FROM         users AS u INNER JOIN
                      question_records AS qr ON qr.user_id = u.id
WHERE     (qr.course_id = #{course.id}) AND (qr.question_id = #{questionid})
GROUP BY u.id

次に、#2の場合:

SELECT qr.id
FROM         questions AS qr2
WHERE      (qr2.course_id = #{course.id}) AND (qr2.question_id = #{questionid}) AND
           (NOT qr.id = (SELECT     MIN(qr.id) AS FirstQRID
                         FROM         users AS u INNER JOIN
                                               question_records AS qr ON qr.user_id = u.id
                         WHERE     (qr.course_id = qr2.course_id) AND (qr.question_id = qr2.quesion_id) AND
                                   (qr.user_id = qr2.user_id)))
于 2012-08-15T21:10:03.183 に答える
0

最初のものには、これで十分なはずです

SELECT qr.id, max(field_1), max(field_2), etc.
FROM users u 
INNER JOIN question_records qr 
ON u.id = qr.user_id
GROUP BY qr.id 
ORDER BY [the field that determines the first question] 

2 番目の質問については、いくつかの選択肢があります。1)選択を行い、アプリケーション層の最初のものを投げるだけです。2) 任意の範囲を返すクエリを開発する

オプション 2 は、グループごとの上位 n 問題として知られていますが、両端で範囲を制限することになります。

于 2012-08-15T20:32:52.093 に答える