2013-02-09 2 views
1

Это довольно простой вопрос, но по какой-то причине я не могу успокоить себя. У меня запрос sql, который я хочу обеспечить, действует, как я ожидаю.Правильно ли подключен этот SQL-запрос?

question_records имеет внешний ключ для обоих enrollments и 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 Другими словами, относится ли это внутреннее соединение к этому, где пункт о записи по записи? Что еще более важно, делает это всегда лечить его так? (Я могу придумать с тестовым примером, но хочу, чтобы убедиться, что я не пропуская случай

Edit:. Дополнительные описательный для ясности:

Вполне возможно, что есть в базе данных с question_record a enrollment_id из 11 и question_id из 500. Если этот запрос не искал условия записи по записи, он будет соответствовать на question_id из 500 и вернуть запись. Это не то поведение, которое я хочу. хотят записи, для которых обаenrollment_idиquestion_id соответствуют данной записи. Ответы, которые я получил это состояние.

+0

Чтобы кто-либо еще мог ответить на ваш вопрос, вам нужно очень четко объяснить, что вы ожидаете от запроса, чтобы вернуться. –

+1

Для конкретной части нет, запрос никогда не вернет строку с «enrollment_id из 11 и question_id из 500». Единственными комбинациями '(enrollment_id, question_id)' являются '(10 500)', '(10,600)', '(20,500)' и '(20,600)' для этого запроса. –

+0

@ypercube Hurgh, хороший улов. Я путаю 'IN' и' BETWEEN'. – millimoose

ответ

0

Ментальная модель для оценки этого запроса является то, что:

  1. Вы хватаете все строки из question_records, enrollments и questions.
  2. Вы создаете декартово произведение этих трех наборов строк. (Сначала соберите все со всем.)
  3. INNER JOIN фильтрует ряды декартового продукта на основании того, соответствуют ли условия ON.
  4. Затем вы отфильтровываете это на основании окончательного состояния WHERE.
  5. Выберите нужный столбцы, чтобы сформировать конечный результат.

(Очевидно, что база данных будет оптимизировать что-то совсем другое.)

Таким образом, если строка соответствует INNER JOIN..ON условиям, но не соответствует WHERE один, он не будет появляться в конечном итоге , Он должен соответствовать всем условиям.

Это может быть легче понять, когда вы знаете, что ваш INNER JOIN эквивалентно следующему: (. Эта форма соответствует ментальной модели я обрисовал лучше)

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)) 

+0

Это отлично. Потратьте время, чтобы понять, что такое INNER JOIN эквивалентно тому, что мне нужно. Спасибо. – JohnMetta

0

Если ваш вопрос, действительно ли оптимизатор SQL будет выталкивать условия из предложения WHERE в JOINs и делать фильтрацию в качестве промежуточного результата для каждой таблицы перед выполнением объединения, тогда ответ заключается в том, что нет такой гарантии, но в простых случаях, подобных этой, достойный оптимизатор.

Смежные вопросы