1

これはかなり基本的な質問ですが、何らかの理由で自分自身を安心させることができません。期待どおりに動作することを確認したいSQLクエリがあります。

question_recordsenrollmentsとの両方の外部キーを持つquestions

SELECT `question_records`.* FROM `question_records` 
  INNER JOIN `enrollments` ON `enrollments`.`id` = `question_records`.`enrollment_id` 
  INNER JOIN `questions` ON `questions`.`id` = `question_records`.`question_id` 
  WHERE (enrollments.id IN (10,20) 
         AND questions.id IN (500,600) 
         AND question_records.id not in (3000,4000))

確認したいのは、たとえば、enrollment_id が 11 で question_id が 500 の質問レコードを取得しないことです。つまり、この内部結合は、この where 句をレコードごとに処理しますか? さらに重要なことに、常にそのように扱っていますか? (テスト例を考え出すことはできますが、ケースを見逃していないことを確認したい.

編集:明確にするための追加の物語:

11 の と 500 の がquestion_recordデータベースに存在する可能性があります。このクエリがレコードごとに条件を検索していない場合、500 の に一致し、レコードを返します。これは私が望む動作ではありません。特定のレコードに対してと両方が一致するレコードのみが必要です。私が得た答えは、この状態をカバーしています。enrollment_idquestion_idquestion_idenrollment_id question_id

4

2 に答える 2

0

このクエリを評価するためのメンタル モデルは次のとおりです。

  1. question_records、、enrollmentsおよびからすべての行を取得しますquestions
  2. これら 3 つの行セットのデカルト積を作成します。(最初はすべてをすべて一致させます。)
  3. は、条件が trueINNER JOINかどうかに基づいてデカルト積の行をフィルター処理します。ON
  4. WHERE次に、最終条件に基づいてこれをフィルタリングします。
  5. 最終結果を形成するために必要な列を選択します。

(明らかに、データベースはそれを完全に別のものに最適化します。)

そのため、行がINNER JOIN..ON条件に一致しても一致しない場合WHERE、最終結果には表示されません。すべての条件に一致する必要があります。

INNER JOINyourがこれと同等であることがわかっている場合、これは理解しやすいかもしれません。

SELECT qr.* FROM question_records qr
                 enrollments      e
                 questions        q
  WHERE e.id = qr.enrollment_id
    AND q.id = qr.question_id
    -- your original WHERE condition
    AND enrollments.id IN (10,20) 
    AND questions.id IN (500,600) 
    AND question_records.id not in (3000,4000))

(この形式は、私が概説したメンタル モデルと一致しています。)

于 2013-02-09T01:27:54.963 に答える
0

SQL オプティマイザが WHERE 句から JOIN に条件をプッシュし、結合を実行する前に各テーブルの中間結果としてフィルタリングを実行するかどうかという質問が本当にある場合、答えはそのような保証はないということですが、次のような単純なケースではこれは、適切なオプティマイザーが行う中途半端なものです。

于 2013-02-09T01:36:51.567 に答える