Большинство диалектов SQL принимают оба следующих запроса:
SELECT a.foo, b.foo
FROM a, b
WHERE a.x = b.x
SELECT a.foo, b.foo
FROM a
LEFT JOIN b ON a.x = b.x
Теперь, очевидно, когда вам нужно внешнее соединение, требуется второй синтаксис. Но при выполнении внутреннего соединения, почему я должен предпочесть второй синтаксис первому (или наоборот)?
Ответы:
Старый синтаксис с простым перечислением таблиц и использованием
WHERE
предложения для указания критериев объединения в большинстве современных баз данных устарел.Это не просто для наглядности, старый синтаксис может быть неоднозначным, когда вы используете как INNER, так и OUTER соединения в одном запросе.
Позвольте привести пример.
Предположим, у вас есть 3 таблицы в вашей системе:
Каждая таблица содержит множество строк, связанных между собой. У вас есть несколько компаний, и в каждой компании может быть несколько отделов, а в каждом отделе может быть несколько сотрудников.
Итак, теперь вы хотите сделать следующее:
Итак, вы делаете это:
Обратите внимание, что у последнего есть внутреннее соединение, чтобы выполнить критерии, которые вы хотите, чтобы отделы только с людьми.
Итак, что происходит сейчас. Проблема в том, что это зависит от механизма базы данных, оптимизатора запросов, индексов и статистики таблиц. Позволь мне объяснить.
Если оптимизатор запросов определит, что способ сделать это - сначала взять компанию, затем найти отделы, а затем выполнить внутреннее объединение с сотрудниками, вы не получите компаний, у которых нет отделов.
Причина этого заключается в том, что
WHERE
предложение определяет, какие строки заканчиваются в конечном результате, а не отдельные части строк.И в этом случае из-за левого соединения столбец Department.ID будет иметь значение NULL, и, таким образом, когда дело доходит до INNER JOIN для Employee, нет способа выполнить это ограничение для строки Employee, и поэтому он не будет появляются.
С другой стороны, если оптимизатор запросов решит сначала выполнить объединение сотрудников и сотрудников, а затем выполнить левое объединение с компаниями, вы их увидите.
Так что старый синтаксис неоднозначен. Нет никакого способа указать, что вы хотите, не имея дело с подсказками запросов, а некоторые базы данных вообще не имеют никакой возможности.
Введите новый синтаксис, с этим вы можете выбрать.
Например, если вы хотите, чтобы все компании, как указано в описании проблемы, вы написали бы следующее:
Здесь вы указываете, что хотите, чтобы объединение сотрудника отдела выполнялось как одно объединение, а затем оставляете объединение результатов с компаниями.
Кроме того, допустим, вам нужны только те отделы, в названии которых есть буква X. Опять же, при объединении в старом стиле вы рискуете потерять и компанию, если у нее нет отделов с X в названии, но с новым синтаксисом вы можете сделать это:
Это дополнительное предложение используется для объединения, но не является фильтром для всей строки. Таким образом, строка может отображаться с информацией о компании, но может содержать значения NULL во всех столбцах отдела и сотрудника для этой строки, поскольку для этой компании не существует отдела с X в названии. Это сложно со старым синтаксисом.
Вот почему, среди других поставщиков, Microsoft устарела старый синтаксис внешнего соединения, но не старый синтаксис внутреннего соединения, начиная с SQL Server 2005 и выше. Единственный способ общения с базой данных, работающей на Microsoft SQL Server 2005 или 2008, с использованием синтаксиса внешнего соединения старого стиля, - это установить эту базу данных в режиме совместимости 8.0 (он же SQL Server 2000).
Кроме того, по-старому, бросая кучу таблиц в оптимизатор запросов с кучей предложений WHERE, было похоже на высказывание «вот, пожалуйста, делай как можно лучше». С новым синтаксисом оптимизатору запросов меньше работы, чтобы выяснить, какие части идут вместе.
Так что у вас есть это.
LEFT и INNER JOIN - это волна будущего.
источник
OUTER JOIN
синтаксис*=
/=*
/*=*
устарел.Синтаксис JOIN сохраняет условия рядом с таблицей, к которой они применяются. Это особенно полезно, когда вы объединяете большое количество таблиц.
Кстати, вы можете также выполнить внешнее соединение с первым синтаксисом:
Или
Или
источник
Первый способ - более старый стандарт. Второй метод был введен в SQL-92, http://en.wikipedia.org/wiki/SQL . Полный стандарт можно посмотреть по адресу http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt .
Прошло много лет, прежде чем компании баз данных приняли стандарт SQL-92.
Таким образом, причина, по которой второй метод является предпочтительным, это стандарт SQL согласно комитету по стандартам ANSI и ISO.
источник
,
все еще стандарт.on
нужно было ввести только для того, чтобыouter join
были также введены подвыборы.По сути, когда ваше предложение FROM перечисляет таблицы следующим образом:
В результате получается перекрестное произведение всех строк в таблицах A, B, C. Затем вы применяете ограничение,
WHERE tableA.id = tableB.a_id
которое отбрасывает огромное количество строк, затем далее ...AND tableB.id = tableC.b_id
и тогда вы должны получить только те строки, которые вам действительно интересны. в.СУБД знают, как оптимизировать этот SQL, чтобы разница в производительности при написании этого с использованием JOIN была незначительной (если есть). Использование нотации JOIN делает оператор SQL более читабельным (IMHO, если не использовать объединения, оператор становится беспорядочным). При использовании перекрестного продукта необходимо указать критерии объединения в предложении WHERE, и это проблема с обозначениями. Вы переполняете свое предложение WHERE такими вещами, как
который используется только для ограничения перекрестного произведения. Предложение WHERE должно содержать ОГРАНИЧЕНИЯ только для набора результатов. Если вы смешаете критерии объединения таблиц с ограничениями набора результатов, вам (и другим) будет труднее читать ваш запрос. Вы обязательно должны использовать JOIN и оставить предложение FROM предложением FROM, а предложение WHERE - предложением WHERE.
источник
Второй вариант предпочтительнее, потому что он с меньшей вероятностью приведет к случайному перекрестному соединению, забыв поставить условие where. Соединение с предложением no on не выполнит проверку синтаксиса, соединение старого стиля с предложением no where не завершится неудачей, оно выполнит перекрестное соединение.
Кроме того, когда вам позже придется присоединиться слева, для обслуживания полезно, чтобы все они были в одной структуре. А старый синтаксис устарел с 1992 года, давно пора перестать его использовать.
Кроме того, я обнаружил, что многие люди, которые используют исключительно первый синтаксис, на самом деле не понимают объединения, и понимание соединений имеет решающее значение для получения правильных результатов при запросах.
источник
Я думаю, что на этой странице есть несколько веских причин для принятия второго метода, использующего явные соединения. Ключевым моментом является то, что когда критерии JOIN удаляются из предложения WHERE, становится намного легче увидеть оставшиеся критерии выбора в предложении WHERE.
В действительно сложных операторах SELECT читателю становится намного легче понять, что происходит.
источник
SELECT * FROM table1, table2, ...
Синтаксис нормально в течение нескольких таблиц, но она становится экспоненциально ( не обязательно математически точное утверждение ) все труднее и труднее читать , как количество таблиц увеличивается.Синтаксис JOIN сложнее написать (в начале), но он делает явным, какие критерии влияют на какие таблицы. Это значительно усложняет ошибку.
Кроме того, если все соединения INNER, то обе версии эквивалентны. Тем не менее, в тот момент, когда вы выполняете OUTER-соединение в любом месте утверждения, все становится намного сложнее, и практически гарантируется, что то, что вы пишете, не будет запрашивать то, что вы написали.
источник
Когда вам нужно внешнее соединение, второй синтаксис не всегда требуется:
Oracle:
MSSQLServer (хотя в версии 2000 г. он устарел ) / Sybase:
Но вернемся к вашему вопросу. Я не знаю ответа, но это, вероятно, связано с тем, что соединение является более естественным (по крайней мере, синтаксически), чем добавление выражения к предложению where , когда вы делаете именно это: соединение .
источник
Я слышал, что многие жалуются, что первый слишком сложен для понимания и неясен. Я не вижу проблемы с этим, но после этого обсуждения я использую второе даже для ВНУТРЕННИХ СОЕДИНЕНИЙ для ясности.
источник
Для базы данных они заканчиваются тем же. Для вас, однако, вам придется использовать этот второй синтаксис в некоторых ситуациях. Ради редактирования запросов, которые в конечном итоге должны использовать его (выяснение, что вам нужно левое соединение, где у вас было прямое соединение), и для согласованности, я бы сделал паттерн только по 2-му методу. Это облегчит чтение запросов.
источник
Первый и второй запросы могут дать разные результаты, потому что LEFT JOIN включает все записи из первой таблицы, даже если в правой таблице нет соответствующих записей.
источник