2014-01-17 10 views
6

Я сегодня ошибся в запросе, но он все еще работал и дал ожидаемый результат. Я имел в виду, чтобы запустить этот запрос:INNER JOIN условие в разделе WHERE?

SELECT e.id FROM employees e JOIN users u ON u.email=e.email WHERE u.id='139840' 

, но я случайно побежал этот запрос

SELECT e.id FROM employees e JOIN users u ON u.email=e.email AND u.id='139840' 

(обратите внимание на AND вместо WHERE в последнем пункте)

и оба вернулись правильный идентификатор сотрудника от идентификатора пользователя.

В чем разница между этими двумя запросами? Включает ли вторая форма только члены из 2 таблиц, удовлетворяющих критериям, тогда как первая будет объединена со всей таблицей, а затем запустит запрос? Является ли он более или менее эффективным, чем другой? Это что-то еще, что мне не хватает?

Спасибо!

+3

Оптимизатор запросов, вероятно, рассматривает их как эквивалент, учитывая, что они имеют тот же смысл ... –

+1

Если вы должны были перейти к LEFT OUTER JOIN, тогда только вторая громкая работа «как и ожидалось» – Strawberry

+0

Возможный дубликат [INNER JOIN ON vs WHERE clause] (http://stackoverflow.com/questions/1018822/inner-join-on-vs-where- оговорка) –

ответ

4

Для внутренних объединений они логически эквивалентны. Однако вы можете работать в ситуациях, когда условие в предложении join означает что-то другое, чем условие в предложении where.

Как простая иллюстрация, представьте, что вы делаете левое соединение таким образом;

select x.id 
from x 
     left join y 
     on x.id = y.id 
; 

Здесь мы берем все строки из x, независимо от того, существует ли соответствующий идентификатор в y. Теперь предположим, что наше условие соединения растет - мы не просто ищем совпадения в y на основе id, но также и id_type.

select x.id 
from x 
     left join y 
     on x.id = y.id 
     and y.id_type = 'some type' 
; 

Снова это дает все строки х независимо от того, существует ли соответствующий (идентификатор, id_type) в г.

Это очень отличается, хотя:

select x.id 
from x 
     left join y 
     on x.id = y.id 
where y.id_type = 'some type' 
; 

В этой ситуации, мы собирание всех строк х и пытаемся соответствовать строкам от у. Теперь для строк, для которых нет совпадения по y, y.id_type будет null. Из-за этого y.id_type = 'some type' не выполняется, поэтому те строки, в которых нет совпадений, отбрасываются, что фактически превращает это в внутреннее соединение.

Короткий рассказ: для внутренних объединений не имеет значения, где условия идут, но для внешних соединений он может.

3

В случае INNER JOIN два запроса семантически одинаковы, что означает, что они гарантированно имеют одинаковые результаты. Если вы использовали соединение OUTER, значение этих двух запросов могло бы быть очень различным, с разными результатами.

Производительность, я бы ожидал, что эти два запроса приведут к такому же плану выполнения. Однако механизм запросов может удивить вас. Единственный способ узнать - просмотреть планы выполнения для двух запросов.

2

Если это внешнее соединение вместо внутреннего, вы получите непреднамеренные результаты, но при использовании внутреннего соединения не имеет никакого значения, используете ли вы дополнительные критерии соединения вместо предложения WHERE.

Показательно, что они скорее всего идентичны, но не могут быть уверенными.

4

Оптимизатор будет относиться к ним одинаково. Вы можете сделать EXPLAIN, чтобы доказать это самому себе.

Следовательно, напишите тот, который яснее.

SELECT e.id 
FROM employees e JOIN users u ON u.email=e.email 
WHERE u.id='139840' 
1

Я рассказал об этом своим коллегам в нашей команде на работе. Этот ответ немного ориентирован на SQL Server, а не на MySQL. Однако оптимизатор должен иметь сходство в работе между SQL и MySQL.

Некоторые мысли: По существу, если вам нужно добавить WHERE, для проверки равенства для каждого условия выполняется дополнительное сканирование таблиц (это повышается на порядков величин с И или набором данных, ИЛИ, решение принимается при первом истинном условии) - если у вас есть один указатель на указатель в приведенном примере, это очень быстро наоборот, если вам нужно найти все записи, которые принадлежат к компании или отделу она становится более неясной, так как вы можете иметь кратность записей. Если вы можете применить условие равенства, это намного эффективнее при работе с таблицей AuditLog или EventLog, в которой есть два ряда строк. На самом деле, на небольших таблицах (около 200 000 строк или около того) не было бы видно больших преимуществ этого.

От: Allesandro Alpi http://suxstellino.wordpress.com/2013/01/07/sql-server-logical-query-processing-summary/

От: Ицик Бен-Ган http://tsql.solidq.com/books/insidetsql2008/Logical%20Query%20Processing%20Poster.pdf

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