Все эти объединения SQL логически эквивалентны? - PullRequest
5 голосов
/ 23 февраля 2009

Мне просто интересно, все ли следующие объединения логически эквивалентны, а если нет, то почему?

SELECT t1.x, t2.y from t1, t2 where t1.a=t2.a and t1.b=t2.b and t1.c = t2.c;

SELECT t1.x, t2.y from t1 join t2 on t1.a=t2.a where t1.b=t2.b and t1.c = t2.c;

SELECT t1.x, t2.y from t1 join t2 on t1.a=t2.a and t1.b=t2.b where t1.c = t2.c;

SELECT t1.x, t2.y from t1 join t2 on t1.a=t2.a and t1.b=t2.b and t1.c = t2.c;

Полагаю, мой настоящий вопрос: объединяет ли «где» с «on» что-то отличное от простого объединения нескольких условий AND вместе с «on»?

Я работаю с MySQL, если это имеет значение.

Ответы [ 4 ]

5 голосов
/ 23 февраля 2009

Они логически эквивалентны и должны давать одинаковый результат. Однако последний вариант предпочтительнее, так как он более правильно указывает семантику запроса, т. Е. «Объединяет таблицы t1 и t2».

Предложение WHERE следует использовать для «фильтрации» результатов объединения - например,

... WHERE t2.some_col > 10

Кроме того, как сказал Константин в другом ответе, 4 запроса были бы другими, если соединение было НАРУЖНЫМ объединением.

2 голосов
/ 23 февраля 2009

Да, как уже говорили другие, результат одинаков для всех этих запросов.

FWIW, вы также можете использовать этот сокращенный синтаксис, когда вы делаете равное объединение для имен столбцов, которые одинаковы в обеих таблицах:

SELECT t1.x, t2.y from t1 join t2 using (a, b, c);

Что касается оптимизации, то следует оптимизировать так же. То есть СУБД должна быть достаточно умной, чтобы анализировать синтаксис WHERE и выполнять соединения вместо генерации промежуточного огромного результата перекрестного объединения и применения к нему условий фильтрации. Это настолько распространенный тип запросов, что для конкретной реализации СУБД также характерно распознавать и оптимизировать его.

В случае MySQL, join и где (вид) оцениваются вместе. Попробуйте использовать EXPLAIN для анализа вашего запроса. Если в столбце «type» указано «eq_ref», это означает, что он использует индексированное соединение. Это лучший тип объединения с точки зрения оптимизации. Если "type" равно "ref", это тоже хорошо.

Эти типы оптимизации объединения можно получить независимо от того, помещаете ли вы условие в предложение JOIN...ON или в предложение WHERE.

2 голосов
/ 23 февраля 2009

Для INNER JOIN это не имеет никакого логического значения, и оптимизатор должен создавать такие же планы. Но для соединений OUTER становится важным, ставите ли вы условие в предложении WHERE или FROM ... JOIN. Это потому, что предложения FROM и ON обрабатываются до предложения WHERE: Обработка логических запросов SQL ANSI http://www.sqlmag.com/Files/09/94378/Figure_01.jpg

1 голос
/ 23 февраля 2009

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

Если в таблице t1, t2 и t3 было по 10 записей каждая, то оператор

SELECT t1.x, t2.y from t1, t2 where t1.a=t2.a and t1.b=t2.b and t1.c = t2.c;

дает 1000 записей перестановки записей трех таблиц, а затем применяется условие where.

Для

SELECT t1.x, t2.y from t1 join t2 on t1.a=t2.a and t1.b=t2.b and t1.c = t2.c;

только десять записей находятся во временной таблице до применения условия where (в данном случае ни одного). Второй метод намного быстрее при работе с большими таблицами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...