В чем разница между "INNER JOIN" и "OUTER JOIN"? - PullRequest
4353 голосов
/ 02 сентября 2008

Кроме того, как вписываются LEFT JOIN, RIGHT JOIN и FULL JOIN?

Ответы [ 24 ]

5797 голосов
/ 02 сентября 2008

Предполагается, что вы объединяетесь в столбцы без дубликатов, что является очень распространенным случаем:

  • Внутреннее соединение A и B дает результат пересечения A B, то есть внутренней части диаграммы Венна пересечения.

  • Внешнее объединение A и B дает результаты объединения A B, то есть внешние части объединения диаграммы Венна.

Примеры

Предположим, у вас есть две таблицы, по одному столбцу в каждой, и данные следующим образом:

A    B
-    -
1    3
2    4
3    5
4    6

Обратите внимание, что (1,2) являются уникальными для A, (3,4) являются общими и (5,6) являются уникальными для B.

Внутреннее соединение

Внутреннее соединение, использующее любой из эквивалентных запросов, дает пересечение двух таблиц, то есть двух общих строк.

select * from a INNER JOIN b on a.a = b.b;
select a.*, b.*  from a,b where a.a = b.b;

a | b
--+--
3 | 3
4 | 4

Левое внешнее соединение

Левое внешнее объединение даст все строки в A плюс все общие строки в B.

select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.*  from a,b where a.a = b.b(+);

a |  b
--+-----
1 | null
2 | null
3 |    3
4 |    4

Правое наружное соединение

Правое внешнее объединение даст все строки в B плюс все общие строки в A.

select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.*  from a,b where a.a(+) = b.b;

a    |  b
-----+----
3    |  3
4    |  4
null |  5
null |  6

полное внешнее соединение

Полное внешнее объединение даст вам объединение A и B, то есть всех строк в A и всех строк в B. Если что-то в A не имеет соответствующих данных в B, то часть B равна нулю и наоборот.

select * from a FULL OUTER JOIN b on a.a = b.b;

 a   |  b
-----+-----
   1 | null
   2 | null
   3 |    3
   4 |    4
null |    6
null |    5
609 голосов
/ 13 декабря 2014

Диаграммы Венна на самом деле не делают это для меня.

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

Ничто не заменит понимание логической обработки, и в любом случае это относительно просто понять.

  1. Представьте себе перекрестное соединение.
  2. Оцените предложение on по всем строкам, начиная с шага 1, сохраняя те, где предикат оценивается как true
  3. (Только для внешних объединений) добавьте обратно во все внешние строки, которые были потеряны на шаге 2.

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

Я начну с анимированной версии полного внешнего соединения . Дальнейшее объяснение следует.

enter image description here


Объяснение

Исходные таблицы

enter link description here

Первый запуск с CROSS JOIN (AKA Cartesian Product). В нем нет предложения ON, а просто возвращается каждая комбинация строк из двух таблиц.

ВЫБРАТЬ A.Colour, B.Colour ОТ CROSS JOIN B

enter link description here

Внутренние и внешние соединения имеют предикат предложения ON.

  • Внутреннее соединение. Оцените условие в предложении "ON" для всех строк в результате перекрестного соединения. Если true, вернуть объединенную строку. В противном случае откажитесь от него.
  • Левое внешнее объединение. То же, что и внутреннее объединение, то для всех строк в левой таблице, которые ничего не соответствуют, выведите их со значениями NULL для правых столбцов таблицы.
  • Правое внешнее соединение. То же самое, что и внутреннее соединение, то для всех строк в правой таблице, которые ничего не соответствуют, выведите их со значениями NULL для левых столбцов таблицы.
  • Полное внешнее соединение. То же, что и внутреннее соединение, затем сохраняются левые несопоставленные строки, как в левом внешнем соединении, и правые несоответствующие строки в соответствии с правым внешним соединением.

Некоторые примеры

ВЫБРАТЬ A.Colour, B.Colour ИЗ ВНУТРЕННЕГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour

Выше приведено классическое равное соединение.

Inner Join

Анимированная версия

enter image description here

ВЫБРАТЬ A.Colour, B.Colour ОТ ВНУТРЕННЕГО СОЕДИНЕНИЯ B НА A.Colour NOT IN («Зеленый», «Синий»)

Условие внутреннего соединения не обязательно должно быть условием равенства и не должно ссылаться на столбцы обеих (или даже обеих) таблиц. Оценка A.Colour NOT IN ('Green','Blue') в каждом ряду результатов перекрестного соединения.

inner 2

ВЫБРАТЬ A.Colour, B.Colour ИЗ ВНУТРЕННЕГО СОЕДИНЕНИЯ B ВКЛ. 1 = 1

Условие соединения оценивается как true для всех строк в результате перекрестного соединения, так что это то же самое, что и перекрестное соединение. Я не буду повторять картину из 16 рядов снова.

ВЫБРАТЬ A.Colour, B.Colour ИЗ ЛЕВОГО НАРУЖНОГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour

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

LOJ

ВЫБРАТЬ A.Colour, B.Colour ИЗ ЛЕВОГО ВНЕШНЕГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour, ГДЕ B.Colour NULL

Это просто ограничивает предыдущий результат, возвращая только те строки, где B.Colour IS NULL. В этом конкретном случае это будут строки, которые были сохранены, так как они не совпадали в правой таблице, и запрос возвращает одну красную строку, не совпадающую в таблице B. Это называется анти-полусоединением.

Важно выбрать столбец для теста IS NULL, который либо не имеет значения NULL, либо для которого условие соединения гарантирует, что любые значения NULL будут исключены, чтобы этот шаблон работал правильно и избегал простого возврата строки, которые имеют значение NULL для этого столбца в дополнение к несоответствующим строкам.

loj is null

ВЫБРАТЬ A.Colour, B.Colour ИЗ ПРАВИЛЬНОГО ВНЕШНЕГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour

Правые внешние объединения действуют аналогично левым внешним соединениям, за исключением того, что они сохраняют несоответствующие строки из правой таблицы и нулевые расширяют левые столбцы.

ROJ

ВЫБРАТЬ A.Colour, B.Colour ИЗ ПОЛНОГО НАРУЖНОГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour

Полные внешние объединения объединяют поведение левого и правого объединений и сохраняют несовпадающие строки из левой и правой таблиц.

FOJ

ВЫБРАТЬ A.Colour, B.Colour ИЗ ПОЛНОГО НАРУЖНОГО СОЕДИНЕНИЯ B ON 1 = 0

Строки в перекрестном соединении не соответствуют предикату 1=0. Все строки с обеих сторон сохраняются с использованием обычных правил внешнего соединения с NULL в столбцах таблицы на другой стороне.

FOJ 2

ВЫБРАТЬ КОАЛЕЦИЮ (A.Colour, B.Colour) КАК ЦВЕТ ИЗ ПОЛНОГО НАРУЖНОГО СОЕДИНЕНИЯ B ON 1 = 0

С незначительной поправкой к предыдущему запросу можно смоделировать UNION ALL из двух таблиц.

UNION ALL

ВЫБРАТЬ A.Colour, B.Colour ИЗ ЛЕВОГО ВНЕШНЕГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour ГДЕ B.Colour = 'Green'

Обратите внимание, что предложение WHERE (если имеется) логически выполняется после объединения. Одной из распространенных ошибок является выполнение левого внешнего соединения, а затем включение предложения WHERE с условием в правой таблице, которое заканчивается исключением несовпадающих строк. Вышеуказанное завершает выполнение внешнего соединения ...

LOJ

... А затем выполняется предложение «Где». NULL= 'Green' не оценивается как истина, поэтому строка, сохраненная внешним соединением, в конечном итоге отбрасывается (вместе с синим), эффективно преобразовывая соединение обратно во внутреннее.

LOJtoInner

Если предполагалось включить только строки из B, где Color - зеленый, и все строки из A независимо от правильного синтаксиса были бы

ВЫБРАТЬ A.Colour, B.Colour ИЗ ЛЕВОГО ВНЕШНЕГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour AND B.Colour = 'Green'

enter image description here

SQL Fiddle

См. Эти примеры run live на SQLFiddle.com .

139 голосов
/ 18 декабря 2014

Соединения используются для объединения данных из двух таблиц, в результате чего получается новая временная таблица. Объединения выполняются на основе того, что называется предикатом, в котором указывается условие, используемое для выполнения объединения. Разница между внутренним соединением и внешним соединением заключается в том, что внутреннее объединение будет возвращать только те строки, которые действительно совпадают, основываясь на предикате соединения. Давайте рассмотрим таблицу сотрудников и местоположения:

enter image description here

Внутреннее присоединение: - Внутреннее объединение создает новую таблицу результатов, комбинируя значения столбцов двух таблиц ( Сотрудник и Местоположение ) на основе предиката соединения. Запрос сравнивает каждую строку Employee с каждой строкой Location , чтобы найти все пары строк, которые удовлетворяют предикату соединения. Когда предикат соединения удовлетворяется путем сопоставления значений, отличных от NULL, значения столбцов для каждой соответствующей пары строк Employee и Location объединяются в строку результатов. Вот как будет выглядеть SQL для внутреннего объединения:

select  * from employee inner join location on employee.empID = location.empID
OR
select  * from employee, location where employee.empID = location.empID

Теперь вот как будет выглядеть результат выполнения SQL: enter image description here enter image description here

Внешнее соединение: - Внешнее соединение не требует, чтобы каждая запись в двух соединенных таблицах имела соответствующую запись. Объединенная таблица сохраняет каждую запись, даже если другой соответствующей записи не существует. Внешние объединения подразделяются далее на левые внешние и правые внешние объединения, в зависимости от того, какие строки таблицы сохраняются (левые или правые).

левое внешнее соединение: - Результат левого внешнего соединения (или просто левого соединения) для таблиц Employee и Location всегда содержит все записи «левой» таблицы ( Employee ), даже если условие соединения не находит подходящую запись в «правильной» таблице ( Location ). Вот как будет выглядеть SQL для левого внешнего соединения, используя таблицы выше:

select  * from employee left outer join location on employee.empID = location.empID;
//Use of outer keyword is optional

Теперь вот как будет выглядеть результат выполнения этого SQL: enter image description here enter image description here

правое внешнее соединение: - Правое внешнее соединение (или правое соединение) очень похоже на левое внешнее соединение, за исключением обработки обращенных таблиц. Каждая строка из «правой» таблицы ( Location ) появится в объединенной таблице хотя бы один раз. Если соответствующая строка из «левой» таблицы ( Employee ) не существует, NULL появится в столбцах из Employee для тех записей, которые не соответствуют в Location . Вот как выглядит SQL:

select * from employee right outer join location  on employee.empID = location.empID;
//Use of outer keyword is optional

Используя таблицы выше, мы можем показать, как будет выглядеть результирующий набор правого внешнего объединения:

enter image description hereenter image description here

полных внешних соединений: - Полное внешнее объединение или полное объединение - это сохранение несоответствующей информации путем включения несоответствующих строк в результаты объединения, использование полного внешнего объединения. Он включает в себя все строки из обеих таблиц, независимо от того, имеет ли другая таблица совпадающее значение. enter image description here

Источник изображения

Справочное руководство по MySQL 8.0 - Синтаксис соединения

Операции соединения Oracle

121 голосов
/ 27 января 2014

Inner Join

Извлекать только совпадающие строки, то есть A intersect B.

Enter image description here

SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
    ON S.Advisor_ID = A.Advisor_ID

левое внешнее соединение

Выбрать все записи из первой таблицы и любые записи во второй таблица, соответствующая соединенным ключам.

Enter image description here

SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
    ON S.Advisor_ID = A.Advisor_ID

полное внешнее соединение

Выберите все записи из второй таблицы и любые записи в первой таблица, соответствующая соединенным ключам.

Enter image description here

SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
    ON S.Advisor_ID = A.Advisor_ID

Ссылки

106 голосов
/ 12 января 2013

Простыми словами:

Внутреннее соединение извлекает только совпадающие строки.

Принимая во внимание, что внешнее объединение извлекает соответствующие строки из одной таблицы и всех строк в другой таблице .... результат зависит от того, какую из них вы используете:

  • Слева : Соответствующие строки в правой таблице и все строки в левой таблице

  • Справа : совпавшие строки в левой таблице и все строки в правой таблице или

  • Полный : Все строки во всех таблицах. Неважно, есть ли совпадение или нет

99 голосов
/ 02 сентября 2008

Внутреннее объединение показывает только строки, если на другой (правой) стороне объединения имеется соответствующая запись.

(левое) внешнее объединение показывает строки для каждой записи с левой стороны, даже если на другой (правой) стороне объединения нет соответствующих строк. Если соответствующая строка отсутствует, столбцы для другой (правой) стороны будут иметь значения NULL.

75 голосов
/ 02 сентября 2008

Внутренние объединения требуют, чтобы в объединенной таблице существовала запись со связанным идентификатором.

Внешние объединения возвращают записи для левой стороны, даже если для правой стороны ничего не существует.

Например, у вас есть таблица Orders и OrderDetails. Они связаны "OrderID".

Заказы

  • OrderID
  • CustomerName

Детали_Заказов

  • OrderDetailID
  • OrderID
  • ProductName
  • Кол-во
  • Цена

Запрос

SELECT Orders.OrderID, Orders.CustomerName
  FROM Orders 
 INNER JOIN OrderDetails
    ON Orders.OrderID = OrderDetails.OrderID

будет возвращать только заказы, которые также имеют что-то в таблице OrderDetails.

Если вы измените его на OUTER LEFT JOIN

SELECT Orders.OrderID, Orders.CustomerName
  FROM Orders 
  LEFT JOIN OrderDetails
    ON Orders.OrderID = OrderDetails.OrderID

тогда он вернет записи из таблицы Orders, даже если у них нет записей OrderDetails.

Вы можете использовать это, чтобы найти Заказы, у которых нет OrderDetails, указывающего возможный потерянный заказ, добавив предложение where как WHERE OrderDetails.OrderID IS NULL.

62 голосов
/ 19 февраля 2015

Простыми словами:

Внутреннее объединение -> Взять ТОЛЬКО общие записи из родительской и дочерней таблиц, ГДЕ первичный ключ родительской таблицы соответствует внешнему ключу в дочерней таблице.

Соединение влево ->

псевдокод

1.Take All records from left Table
2.for(each record in right table,) {
    if(Records from left & right table matching on primary & foreign key){
       use their values as it is as result of join at the right side for 2nd table.
    } else {
       put value NULL values in that particular record as result of join at the right side for 2nd table.
    }
  }

Правое соединение : Точно напротив левого соединения. Поместите имя таблицы в LEFT JOIN справа от правого соединения, вы получите тот же вывод, что и в LEFT JOIN.

Наружное соединение : Показать все записи в обеих таблицах No matter what. Если записи в левой таблице не совпадают с правой таблицей на основе первичного ключа и ключа Forieign, используйте значение NULL в качестве результата объединения.

Пример:

Example

Предположим теперь для 2 таблиц

1.employees , 2.phone_numbers_employees

employees : id , name 

phone_numbers_employees : id , phone_num , emp_id   

Здесь таблица employee - это главная таблица, phone_numbers_employees - это дочерняя таблица (она содержит emp_id в качестве внешнего ключа, который соединяет employee.id и его дочернюю таблицу.)

Внутренние соединения

Взять записи из 2 таблиц ТОЛЬКО ЕСЛИ соответствует первичный ключ таблицы сотрудников (его идентификатор) Внешний ключ дочерней таблицы phone_numbers_employees (emp_id) .

Таким образом, запрос будет:

SELECT e.id , e.name , p.phone_num FROM employees AS e INNER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;

Здесь берутся только совпадающие строки в первичном ключе = внешний ключ, как описано выше. Здесь несоответствующие строки в первичном ключе = внешний ключ пропускаются в результате объединения.

Левые соединения :

Левое объединение сохраняет все строки левой таблицы, независимо от того, есть ли строка, соответствующая правой таблице.

SELECT e.id , e.name , p.phone_num FROM employees AS e LEFT JOIN phone_numbers_employees AS p ON e.id = p.emp_id;

Внешние соединения :

SELECT e.id , e.name , p.phone_num FROM employees AS e OUTER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;

Схематически это выглядит так:

Diagram

55 голосов
/ 27 сентября 2012

Вы используете INNER JOIN, чтобы вернуть все строки из обеих таблиц, где есть совпадение. в полученной таблице все строки и столбцы будут иметь значения.

В OUTER JOIN в результирующей таблице могут быть пустые столбцы. Внешнее соединение может быть либо LEFT, либо RIGHT.

LEFT OUTER JOIN возвращает все строки из первой таблицы, даже если во второй таблице нет совпадений.

RIGHT OUTER JOIN возвращает все строки из второй таблицы, даже если в первой таблице нет совпадений.

54 голосов
/ 22 марта 2016

This is a good explanation for joins

Это хорошее схематичное объяснение для всех видов соединений

источник: http://ssiddique.info/understanding-sql-joins-in-easy-way.html

...