Диаграммы Венна на самом деле не делают это для меня.
Они не показывают какого-либо различия между перекрестным соединением и внутренним объединением, например, или, в более общем случае, показывают какое-либо различие между различными типами предикатов объединения или предоставляют основу для рассуждений о том, как они будут работать.
Ничто не заменит понимание логической обработки, и в любом случае это относительно просто понять.
- Представьте себе перекрестное соединение.
- Оцените предложение
on
по всем строкам, начиная с шага 1, сохраняя те, где предикат оценивается как true
- (Только для внешних объединений) добавьте обратно во все внешние строки, которые были потеряны на шаге 2.
(Примечание: на практике оптимизатор запросов может найти более эффективные способы выполнения запроса, чем приведенное выше чисто логическое описание, но конечный результат должен быть таким же)
Я начну с анимированной версии полного внешнего соединения . Дальнейшее объяснение следует.
Объяснение
Исходные таблицы
Первый запуск с CROSS JOIN
(AKA Cartesian Product). В нем нет предложения ON
, а просто возвращается каждая комбинация строк из двух таблиц.
ВЫБРАТЬ A.Colour, B.Colour ОТ CROSS JOIN B
Внутренние и внешние соединения имеют предикат предложения ON.
- Внутреннее соединение. Оцените условие в предложении "ON" для всех строк в результате перекрестного соединения. Если true, вернуть объединенную строку. В противном случае откажитесь от него.
- Левое внешнее объединение. То же, что и внутреннее объединение, то для всех строк в левой таблице, которые ничего не соответствуют, выведите их со значениями NULL для правых столбцов таблицы.
- Правое внешнее соединение. То же самое, что и внутреннее соединение, то для всех строк в правой таблице, которые ничего не соответствуют, выведите их со значениями NULL для левых столбцов таблицы.
- Полное внешнее соединение. То же, что и внутреннее соединение, затем сохраняются левые несопоставленные строки, как в левом внешнем соединении, и правые несоответствующие строки в соответствии с правым внешним соединением.
Некоторые примеры
ВЫБРАТЬ A.Colour, B.Colour ИЗ ВНУТРЕННЕГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour
Выше приведено классическое равное соединение.
Анимированная версия
ВЫБРАТЬ A.Colour, B.Colour ОТ ВНУТРЕННЕГО СОЕДИНЕНИЯ B НА A.Colour NOT IN («Зеленый», «Синий»)
Условие внутреннего соединения не обязательно должно быть условием равенства и не должно ссылаться на столбцы обеих (или даже обеих) таблиц. Оценка A.Colour NOT IN ('Green','Blue')
в каждом ряду результатов перекрестного соединения.
ВЫБРАТЬ A.Colour, B.Colour ИЗ ВНУТРЕННЕГО СОЕДИНЕНИЯ B ВКЛ. 1 = 1
Условие соединения оценивается как true для всех строк в результате перекрестного соединения, так что это то же самое, что и перекрестное соединение. Я не буду повторять картину из 16 рядов снова.
ВЫБРАТЬ A.Colour, B.Colour ИЗ ЛЕВОГО НАРУЖНОГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour
Внешние объединения логически оцениваются так же, как и внутренние соединения, за исключением того, что если строка из левой таблицы (для левого объединения) вообще не объединяется ни с одной строкой из правой таблицы, она сохраняется в результате с NULL
значения для правых столбцов.
ВЫБРАТЬ A.Colour, B.Colour ИЗ ЛЕВОГО ВНЕШНЕГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour, ГДЕ B.Colour NULL
Это просто ограничивает предыдущий результат, возвращая только те строки, где B.Colour IS NULL
. В этом конкретном случае это будут строки, которые были сохранены, так как они не совпадали в правой таблице, и запрос возвращает одну красную строку, не совпадающую в таблице B
. Это называется анти-полусоединением.
Важно выбрать столбец для теста IS NULL
, который либо не имеет значения NULL, либо для которого условие соединения гарантирует, что любые значения NULL
будут исключены, чтобы этот шаблон работал правильно и избегал простого возврата строки, которые имеют значение NULL
для этого столбца в дополнение к несоответствующим строкам.
ВЫБРАТЬ A.Colour, B.Colour ИЗ ПРАВИЛЬНОГО ВНЕШНЕГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour
Правые внешние объединения действуют аналогично левым внешним соединениям, за исключением того, что они сохраняют несоответствующие строки из правой таблицы и нулевые расширяют левые столбцы.
ВЫБРАТЬ A.Colour, B.Colour ИЗ ПОЛНОГО НАРУЖНОГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour
Полные внешние объединения объединяют поведение левого и правого объединений и сохраняют несовпадающие строки из левой и правой таблиц.
ВЫБРАТЬ A.Colour, B.Colour ИЗ ПОЛНОГО НАРУЖНОГО СОЕДИНЕНИЯ B ON 1 = 0
Строки в перекрестном соединении не соответствуют предикату 1=0
. Все строки с обеих сторон сохраняются с использованием обычных правил внешнего соединения с NULL в столбцах таблицы на другой стороне.
ВЫБРАТЬ КОАЛЕЦИЮ (A.Colour, B.Colour) КАК ЦВЕТ ИЗ ПОЛНОГО НАРУЖНОГО СОЕДИНЕНИЯ B ON 1 = 0
С незначительной поправкой к предыдущему запросу можно смоделировать UNION ALL
из двух таблиц.
ВЫБРАТЬ A.Colour, B.Colour ИЗ ЛЕВОГО ВНЕШНЕГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour ГДЕ B.Colour = 'Green'
Обратите внимание, что предложение WHERE
(если имеется) логически выполняется после объединения. Одной из распространенных ошибок является выполнение левого внешнего соединения, а затем включение предложения WHERE с условием в правой таблице, которое заканчивается исключением несовпадающих строк. Вышеуказанное завершает выполнение внешнего соединения ...
... А затем выполняется предложение «Где». NULL= 'Green'
не оценивается как истина, поэтому строка, сохраненная внешним соединением, в конечном итоге отбрасывается (вместе с синим), эффективно преобразовывая соединение обратно во внутреннее.
Если предполагалось включить только строки из B, где Color - зеленый, и все строки из A независимо от правильного синтаксиса были бы
ВЫБРАТЬ A.Colour, B.Colour ИЗ ЛЕВОГО ВНЕШНЕГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour AND B.Colour = 'Green'
SQL Fiddle
См. Эти примеры run live на SQLFiddle.com .