В чем разница между «INNER JOIN» и «OUTER JOIN»?


4672

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


64
Из приведенных ниже ответов, комментариев и ссылок на них только один на самом деле объясняет, как диаграммы Венна представляют операторы: Область пересечения окружности представляет собой набор строк в A JOIN B. Область, уникальная для каждого круга, представляет собой набор строк, которые вы получаете, взяв его Строки таблицы, которые не участвуют в A JOIN B и добавляют столбцы, уникальные для другой таблицы, все имеют значение NULL. (И большинство дают смутное поддельное соответствие кругов А и Б.)
philipxy

1
Переходя от теоретических ответов ниже к реальному приложению: я часто работаю с экспериментальными данными, выполняя тесты по процессорам. Часто я хочу сравнить результаты между двумя или более аппаратными опциями. INNER JOIN означает, что я вижу только те тесты, которые были успешно выполнены во всех экспериментах; OUTER JOIN означает, что я вижу все эксперименты, в том числе те, которые не удалось запустить на некоторых конфигурациях. Важно видеть неудачи в таких экспериментах, а также успехи. Достаточно важно, что я написал PerlSQL, чтобы получить OUTER JOIN, когда этого не хватало многим РСУБД,
Krazy Glew

4
Многие ответы уже предоставлены, но я не видел этот учебник упомянутым. Если вы знаете диаграммы Венна, это БОЛЬШОЙ учебник: blog.codinghorror.com/a-visual-explanation-of-sql-joins Для меня это достаточно лаконично, чтобы быстро прочитать, но все же охватывает всю концепцию и работает все дела очень хорошо. Если вы не знаете, что такое диаграммы Венна, изучите их. Займет 5-10 минут, чтобы помочь вам, когда вам нужно будет визуализировать работу с наборами и управление операциями над наборами.
DanteTheSmith

15
@DanteTheSmith Нет, это страдает от тех же проблем, что и диаграммы здесь. См. Мой комментарий выше относительно вопроса и ниже того самого сообщения в блоге: «Джефф отказывается от своего блога на несколько страниц внизу в комментариях». Диаграммы Венна показывают элементы в наборах. Просто попробуйте точно определить, что это за наборы и каковы элементы этих диаграмм. Наборы не являются таблицами, а элементы не являются их строками. Также любые две таблицы могут быть объединены, поэтому PK и FK не имеют значения. Все поддельные. Вы делаете только то , что тысячи других сделали - получили смутное впечатление вы (ошибочно) полагать , имеет смысл.
Philipxy

3
Крис, я рекомендую вам прочитать эту статью: vs.datascience.com/… ... и подумать о том, чтобы сменить выбранный вами вариант ответа (возможно, на тот, у кого есть награда) на ответ, в котором не используются диаграммы Венна. В настоящее время принятый ответ вводит в заблуждение слишком многих людей. Я призываю вас сделать это на благо нашего сообщества и качества нашей базы знаний.
Колм Бхандал

Ответы:


6116

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

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

  • Внешнее объединение A и B дает результаты объединения 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

42
Было бы хорошо дополнить пример, добавив еще одну строку в таблицу B со значением 4. Это покажет, что внутренние объединения не обязательно должны быть равными ни одному из рядов.
софтведа

473
Прекрасное объяснение, однако, это утверждение: внешнее объединение A и B дает результаты объединения B, то есть внешние части объединения диаграммы Венна. не сформулировано точно. Внешнее соединение даст результаты пересечения B с B в дополнение к одному из следующих: все A (левое соединение), все B (правое соединение) или все A и все B (полное соединение). Только этот последний сценарий действительно является союзом Б. Тем не менее, хорошо написанное объяснение.
Томас

11
Прав ли я, что FULL JOIN является псевдонимом FULL OUTER JOIN, а LEFT JOIN является псевдонимом LEFT OUTER JOIN?
Дамиан

3
да отличное и отличное объяснение. но почему в столбце b значения не в порядке? то есть это 6,5 не как 5,6?
Амир

7
@ Амир, спасибо. Регистрация не гарантирует заказ, вам нужно добавить предложение ORDER BY.
Марк Харрисон

734

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

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

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

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

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

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

введите описание изображения здесь


объяснение

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

введите описание ссылки здесь

Сначала начните с CROSS JOIN(AKA декартово произведение). Это не имеет ONпредложения и просто возвращает каждую комбинацию строк из двух таблиц.

ВЫБЕРИТЕ А.ЦВЕТ, Б.ЦВЕТ ИЗ КРЕСТА СОЕДИНИТЕ 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')по каждому ряду результатов перекрестного соединения.

внутренний 2

ВЫБЕРИТЕ A.Colour, B.Colour ИЗ ВНУТРЕННЕГО СОЕДИНЕНИЯ B ON 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 is NULL

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

Важно выбрать столбец для IS NULLтеста, который не имеет значения NULL или для которого условие соединения гарантирует, что любые NULLзначения будут исключены, чтобы этот шаблон работал правильно, и избегал просто возвращать строки, которые, как оказалось, имеют 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

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

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

СОЮЗ ВСЕХ

ВЫБЕРИТЕ A.Colour, B.Colour ИЗ ЛЕВОГО ВНЕШНЕГО СОЕДИНЕНИЯ B НА A.Colour = B.Colour ГДЕ B.Colour = 'Зеленый'

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

LOJ

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

LOJtoInner

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

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

введите описание изображения здесь

SQL Fiddle

Посмотрите эти примеры в прямом эфире на SQLFiddle.com .


46
Я скажу, что хотя это не работает для меня так же хорошо, как диаграммы Венна, я ценю, что люди меняются и учатся по-разному, и это очень хорошо представленное объяснение, в отличие от того, что я видел раньше, поэтому я поддерживаю @ypercube в начисление бонусных баллов. Также хорошая работа, объясняющая разницу в размещении дополнительных условий в предложении JOIN по сравнению с предложением WHERE. Слава тебе, Мартин Смит.
Старый Про

22
@OldPro Диаграммы Венна в порядке, я думаю, но они ничего не говорят о том, как представлять перекрестное соединение или различать один тип предиката соединения, например, равное соединение, от другого. Ментальная модель оценки предиката соединения в каждой строке результата перекрестного соединения, затем добавление обратно в несопоставленные строки, если внешнее соединение, и, наконец, оценка местоположения лучше работает для меня.
Мартин Смит

18
Диаграммы Венна хороши для представления союзов, пересечений и различий, но не для соединений. Они имеют небольшую образовательную ценность для очень простых объединений, то есть объединений, где условие объединения находится в уникальных столбцах.
ypercubeᵀᴹ

12
@Arth - Нет, ты не прав. SQL Fiddle sqlfiddle.com/#!3/9eecb7db59d16c80417c72d1/5155 это то, что диаграммы Венна не могут проиллюстрировать.
Мартин Смит

7
@MartinSmith Ого, я согласен, я совершенно не прав! Слишком привык работать с одним человеком ... спасибо за исправление.
Арт

188

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

введите описание изображения здесь

Внутреннее объединение : - Внутреннее объединение создает новую таблицу результатов, комбинируя значения столбцов двух таблиц ( Employee и Location ) на основе предиката объединения. Запрос сравнивает каждую строку 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: введите описание изображения здесь

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

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

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

Теперь вот как будет выглядеть результат выполнения этого SQL: введите описание изображения здесь

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

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

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

введите описание изображения здесь

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

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

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

Операции Oracle Join


3
лучший ответ на данный момент, альтернативный синтаксис - это то, что я искал, спасибо!
Джои

1
Диаграммы Венна неверно обозначены. Смотрите мои комментарии на вопрос и другие ответы. Также большая часть этого языка бедна. Например: «Когда предикат соединения удовлетворяется путем сопоставления значений, отличных от NULL, значения столбцов для каждой соответствующей пары строк Employee и Location объединяются в строку результатов». Нет, не «Когда предикат соединения удовлетворяется путем сопоставления ненулевых значений». Значения в строках не имеют значения, кроме того, является ли условие в целом истинным или ложным. Некоторые значения могут быть NULL для истинного условия.
Philipxy

Хотя это явно не указано, диаграммы в этом являются диаграммами Венна. Диаграммы Венна, как правило, не являются правильной математической характеристикой объединения. Я предлагаю удалить диаграммы Венна.
Колм Бхандал

@ColmBhandal: удалены диаграммы Венна
ajitksharma

Пожалуйста, используйте текст, а не изображения / ссылки, для текста - включая таблицы и ERD . Используйте изображения только для того, что не может быть выражено как текст или для увеличения текста. Изображения не могут быть найдены или вырезаны и вставлены. Включите легенду / ключ и объяснение с изображением.
Филипп

133

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

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

Введите описание изображения здесь

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

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

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

Введите описание изображения здесь

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

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

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

Введите описание изображения здесь

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

Ссылки


14
Как называется инструмент? Я нахожу это интересным, так как показывает количество строк и диаграмм
Венна

2
@GrijeshChauhan Да, но вы можете попробовать запустить его с помощью вина .
Тушар Гупта - curioustushar

2
Оу! да я .. я использовал SQLyog с помощью вина .. есть также PlayOnLinux
Grijesh Chauhan

1
Ваш текст неясен и неправильный. «Только совпадающие строки» являются строками из перекрестного соединения A & B, и то, что извлекается (внутреннее соединение B), не пересекается с B, а (левое соединение B) пересекается (правое соединение B). «Выбранные» строки не из A & B, они из A перекрестного соединения B & из расширенных нулями значений строк из A & B.
philipxy

@ TusharGupta-curioustushar вы должны включить «Таблицы, используемые для примеров SQL»
Мануэль Джордан

112

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

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

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

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

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

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


1
@nomen Не то, чтобы этот ответ обращался к нему, но INNER JOIN является пересечением, а FULL OUTER JOIN является соответствующим UNION, если левый и правый наборы / окружности содержат строки (соответственно) соединения LEFT и RIGHT. PS Этот ответ неясен для строк во входных и выходных данных. Он путает «в левой / правой таблице» с «имеет левую / правую часть в левой / правой» и использует «совпадающую строку» против «все» для обозначения строки, расширенной строкой из другой таблицы, против нуля.
Филипп

104

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

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


82

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

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

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

заказы

  • Номер заказа
  • Имя покупателя

Информация для заказа

  • OrderDetailID
  • Номер заказа
  • Наименование товара
  • Кол-во
  • Цена

Запрос

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.


1
Я ценю простой, но реалистичный пример. Я изменил запрос , как SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c, categories_description cd WHERE c.id = cd.categories_id AND c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASCв SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c INNER JOIN categories_description cd ON c.id = cd.categories_id WHERE c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASC(MySQL) с успехом. Я не был уверен насчет дополнительных условий, они хорошо сочетаются ...
PhiLho

68

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

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

Осталось присоединиться ->

псевдокод

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 в качестве результата объединения.

Пример :

пример

Предположим теперь для 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;

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

схема


4
Результат не имеет ничего общего с первичными / уникальными / потенциальными ключами и внешними ключами. Бавур может и должен быть описан без ссылки на них. Рассчитывается перекрестное соединение, затем отфильтровываются строки, не соответствующие условию ON; дополнительно для внешних объединений строки, отфильтрованные / несопоставленные, расширяются значениями NULL (согласно LEFT / RIGHT / FULL и включены.
philipxy

Предположение, что соединения SQL всегда совпадают с первичными / внешними ключами, приводит к неправильному использованию диаграмм Венна. Пожалуйста, измените свой ответ соответственно.
Колм Бхандал

58

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

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

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

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


56

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

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

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


1
Этот пост не дает четкого объяснения, как интерпретировать эту диаграмму. Также см. Первый комментарий к вопросу и мои другие комментарии на этой странице.
Philipxy

54

INNER JOINтребует, чтобы при сравнении двух таблиц было как минимум совпадение. Например, таблица A и таблица B, которые подразумевают A ٨ B (пересечение A B).

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

Аналогично RIGHT OUTER JOINи RIGHT JOINодинаковы. Это дает все записи, совпадающие в обеих таблицах и все возможности правой таблицы.

FULL JOINэто комбинация LEFT OUTER JOINи RIGHT OUTER JOINбез дублирования.


43

Ответ заключается в значении каждого, так и в результатах.

Примечание:
В SQLiteне существует RIGHT OUTER JOINили FULL OUTER JOIN.
А также в MySQLнет FULL OUTER JOIN.

Мой ответ основан на примечании выше .

Когда у вас есть две таблицы, подобные этим:

--[table1]               --[table2]
id | name                id | name
---+-------              ---+-------
1  | a1                  1  | a2
2  | b1                  3  | b2

CROSS JOIN / OUTER JOIN:
Вы можете иметь все данные этих таблиц с CROSS JOINили просто ,так:

SELECT * FROM table1, table2
--[OR]
SELECT * FROM table1 CROSS JOIN table2

--[Results:]
id | name | id | name 
---+------+----+------
1  | a1   | 1  | a2
1  | a1   | 3  | b2
2  | b1   | 1  | a2
2  | b1   | 3  | b2

ВНУТРЕННЕЕ СОЕДИНЕНИЕ:
если вы хотите добавить фильтр к вышеуказанным результатам на основе отношения, которое table1.id = table2.idвы можете использовать INNER JOIN:

SELECT * FROM table1, table2 WHERE table1.id = table2.id
--[OR]
SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id

--[Results:]
id | name | id | name 
---+------+----+------
1  | a1   | 1  | a2

LEFT [OUTER] JOIN:
Если вы хотите, чтобы все строки одной из таблиц в приведенном выше результате - с одинаковым отношением - вы можете использовать LEFT JOIN:
(Для RIGHT JOIN просто измените место таблиц)

SELECT * FROM table1, table2 WHERE table1.id = table2.id 
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
--[OR]
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id

--[Results:]
id | name | id   | name 
---+------+------+------
1  | a1   | 1    | a2
2  | b1   | Null | Null

FULL OUTER JOIN:
Если вы также хотите, чтобы в ваших результатах были все строки другой таблицы, вы можете использовать FULL OUTER JOIN:

SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
UNION ALL
SELECT Null, Null, * FROM table2 WHERE Not table2.id In (SELECT id FROM table1)
--[OR] (recommended for SQLite)
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
UNION ALL
SELECT * FROM table2 LEFT JOIN table1 ON table2.id = table1.id
WHERE table1.id IS NULL
--[OR]
SELECT * FROM table1 FULL OUTER JOIN table2 On table1.id = table2.id

--[Results:]
id   | name | id   | name 
-----+------+------+------
1    | a1   | 1    | a2
2    | b1   | Null | Null
Null | Null | 3    | b2

Ну, так как вам нужно, вы выбираете каждый, который покрывает ваши потребности;).


Вы можете добавить к своей заметке, что full outer joinв MySQL ее тоже нет.
поташин

35

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

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

Внешнее Присоединение.

Влево присоединиться попытками найти совпасть строки из первой таблицы , в строки во второй таблице. Если он не может найти совпадение, он вернет столбцы из первой таблицы и оставит столбцы из второй таблицы пустыми (пустыми).


28

введите описание изображения здесь

  • INNER JOINнаиболее типичное объединение для двух или более таблиц. Возвращает совпадение данных как для таблицы ON primarykey, так и для отношения forignkey.
  • OUTER JOINтак же, как INNER JOIN, но он также включает в себя NULLданные на ResultSet.
    • LEFT JOIN= INNER JOIN+ Несоответствующие данные левой таблицы с Nullсовпадением на правой таблице.
    • RIGHT JOIN= INNER JOIN+ Несоответствующие данные правой таблицы с Nullсовпадением на левой таблице.
    • FULL JOIN= INNER JOIN+ Несоответствующие данные в правой и левой таблицах с Nullсовпадениями.
  • Самосоединение не является ключевым словом в SQL, когда таблица ссылается на данные, которые сами по себе называются самосоединением. Используя INNER JOINи OUTER JOINмы можем написать запросы на самостоятельное соединение.

Например:

SELECT * 
FROM   tablea a 
       INNER JOIN tableb b 
               ON a.primary_key = b.foreign_key 
       INNER JOIN tablec c 
               ON b.primary_key = c.foreign_key 

27

Я не вижу подробностей о производительности и оптимизаторе в других ответах.

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

Как правило, рекомендуется использовать INNER JOINвместо разных видов соединений. (Конечно, если это возможно, учитывая ожидаемый набор результатов.)

Здесь есть несколько хороших примеров и объяснений об этом странном ассоциативном поведении:


4
Не может быть "хорошей практикой" использовать один тип соединения поверх другого. Какое соединение вы используете, определяет данные, которые вы хотите. Если вы используете другой, вы не правы. Плюс, в Oracle, по крайней мере, этот ответ совершенно неверен. Это звучит совершенно неправильно для всех, и у вас нет никаких доказательств. У тебя есть доказательства?
Бен

1. Я имею в виду, попробуйте использовать. Я видел много людей, использующих LEFT OUTER соединения везде без какой-либо веской причины. (Объединенные столбцы были «не нулевыми».) В этих случаях было бы определенно лучше использовать INNER объединения. 2. Я добавил ссылку, объясняющую неассоциативное поведение лучше, чем я мог.
Лайос Верес

Как я знаю, INNER JOINэто медленнее, чем LEFT JOINв большинстве случаев, и люди могут использовать LEFT JOINвместо INNER JOINдобавления WHEREдля удаления неожиданных NULLрезультатов;).
shA.t

Эти комментарии сделали меня немного неуверенным. Как вы думаете, почему INNERмедленнее?
Лайос Верес

Зависит от двигателя. gnu join, joinkeys, DB2, MySQL. Производительные ловушки имеются в большом количестве, такие как свободная типизация или явное приведение.
Маккензм

26

Покритиковав столь любимую диаграмму Венна в красных тонах, я подумал, что будет справедливо опубликовать мою собственную попытку.

Несмотря на то, что ответ @Martin Smith является лучшим из этой группы, он показывает только ключевые столбцы из каждой таблицы, в то время как я считаю, что в идеале также должны быть показаны неключевые столбцы.

Лучшее, что я мог бы сделать за полчаса, я все еще не думаю, что это адекватно показывает, что нулевые значения присутствуют из-за отсутствия значений ключей TableBили что OUTER JOINэто фактически объединение, а не соединение:

введите описание изображения здесь


2
Вопрос просит разницу между внутренними и наружными присоединяется хотя, не обязательно левое внешнее соединение лол
LearnByReading

@LearnByReading: моя картинка справа - это правое внешнее соединение, то есть замена TableA a LEFT OUTER JOIN TableB bнаTableB B RIGHT OUTER JOIN TableA a
onedaywhen

26

Точный алгоритм для INNER JOIN, LEFT/RIGHT OUTER JOINявляются следующие:

  1. Возьмите каждый ряд из первой таблицы: a
  2. Рассмотрим все строки из второй таблицы рядом с ним: (a, b[i])
  3. Оцените ON ...предложение по каждой паре:ON( a, b[i] ) = true/false?
    • Когда условие оценивается как true, вернуть эту объединенную строку (a, b[i]).
    • Когда достигается конец второй таблицы без какого-либо соответствия, и это Outer Joinвозвращает (виртуальную) пару, используя Nullдля всех столбцов другой таблицы: (a, Null)для внешнего соединения LEFT или (Null, b)для внешнего соединения RIGHT. Это должно гарантировать, что все строки первой таблицы существуют в окончательных результатах.

Примечание: условие, указанное в ONпредложении, может быть любым, необязательно использовать первичные ключи (и вам не нужно всегда ссылаться на столбцы из обеих таблиц)! Например:

Внутреннее соединение против левого внешнего соединения


введите описание изображения здесь

Примечание: левое соединение = левое внешнее соединение, правое соединение = правое внешнее соединение.


20

Простейшие определения

Внутреннее объединение: возвращает сопоставленные записи из обеих таблиц.

Полное внешнее объединение: возвращает сопоставленные и несопоставленные записи из обеих таблиц со значением NULL для несопоставленных записей из обеих таблиц .

Левое внешнее объединение: возвращает сопоставленные и несопоставленные записи только из таблицы на левой стороне .

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

Короче говоря

Совпадение + Несоответствие слева + Несоответствие справа = Полное внешнее соединение

Совпадение + Левое Несоответствие = Левое внешнее соединение

Совпадение + Право Несоответствие = Право Наружное соединение

Matched = Inner Join


1
Это замечательно и объясняет, почему объединение не работает так, как ожидалось для индексов временных рядов. Отметки времени на расстоянии одной секунды не имеют себе равных.
Йелиабсалоцин

1
@yeliabsalohcin Вы не объясняете «как ожидалось» здесь или «работает» в своем комментарии к вопросу. Это просто какое-то необъяснимое личное заблуждение, которое, как ни странно, ожидают другие. Если вы воспринимаете слова как небрежные, когда вы читаете - неправильно истолковываете ясное письмо и / или принимаете нечеткое письмо - как, когда вы пишете здесь, тогда вы можете ожидать ошибочных представлений. На самом деле этот ответ, как и большинство здесь, неясен и неправильный. «Внутреннее объединение: возвращает сопоставленные записи из обеих таблиц» неправильно, если наборы входных столбцов различаются. Он пытается что-то сказать, но это не так . (См. Мой ответ.)
philipxy

9

Проще говоря,

1. INNER JOIN ИЛИ EQUI JOIN: Возвращает набор результатов, который соответствует только условию в обеих таблицах.

2. ВНЕШНЕЕ СОЕДИНЕНИЕ: возвращает набор результатов всех значений из обеих таблиц, даже если условие соответствует или нет.

3. LEFT JOIN: возвращает набор результатов всех значений из левой таблицы и только строк, соответствующих условию в правой таблице.

4. RIGHT JOIN: возвращает набор результатов всех значений из правой таблицы и только строк, соответствующих условию в левой таблице.

5. ПОЛНОЕ СОЕДИНЕНИЕ: полное соединение и полное внешнее соединение - это одно и то же.


5

Существует два основных типа соединений в SQL: [INNER и OUTER]


Примеры

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

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

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



  • (ВНУТРЕННИЙ) ПРИСОЕДИНЯЙТЕСЬ :

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

ВНУТРЕННЕЕ СОЕДИНЕНИЕ

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


  • ЛЕВЫЙ (НАРУЖНЫЙ) ПРИСОЕДИНЯЙТЕСЬ :

Это объединение возвращает все строки таблицы с левой стороны объединения и совпадающие строки для таблицы с правой стороны объединения. Строки, для которых нет подходящей строки на правой стороне, результирующий набор будет содержать нуль. LEFT JOIN также известен как LEFT OUTER JOIN.

ЛЕВОЕ СОЕДИНЕНИЕ / ЛЕВОЕ НАРУЖНОЕ СОЕДИНЕНИЕ

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
7 | null
8 | null


  • RIGHT (OUTER) JOIN : возвращает все записи из правой таблицы и сопоставленные записи из левой таблицы

ПРАВИЛЬНОЕ СОЕДИНЕНИЕ / ПРАВО НАРУЖНОЕ СОЕДИНЕНИЕ

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


  • ПОЛНОЕ (НАРУЖНОЕ) РЕШЕНИЕ :

    FULL JOIN создает результирующий набор, комбинируя результат как LEFT JOIN, так и RIGHT JOIN. Результирующий набор будет содержать все строки из обеих таблиц. Строки, для которых нет соответствия, набор результатов будет содержать значения NULL.

ПОЛНОЕ СОЕДИНЕНИЕ / ПОЛНОЕ НАРУЖНОЕ СОЕДИНЕНИЕ

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
   7 | null
   8 | null

1
Диаграммы Венна не достаточно для описания соединений SQL в общем случае. Соединения SQL не обязательно должны совпадать строки между таблицами один-к-одному, например, с использованием внешнего ключа и первичного ключа.
Колм Бхандал

Как объединить 2 таблицы без совпадения строки? Вам нужен первичный или внешний ключ столбца или какое-то общее поле, чтобы вы могли выполнить соединение. Мне интересно, почему вы понизили этот ответ. И диаграмма Венна является источником, объясняющим, как работает SQL JOIN. Есть ли у вас лучшие примеры для представления соединений? Если нет, пожалуйста, проголосуйте, чтобы люди получили лучшие решения. Спасибо.
Майур

Вы тот, кто помещает диаграммы в пост. Какова легенда для диаграмм? - Каковы элементы каждого набора? А как насчет того, что столы - это сумки, а не наборы? Вы не говорите. Одна вещь, из которой они не являются наборами - это строки A & B на ярлыки. Смотрите мои комментарии к сообщениям на этой странице. Этот пост просто слепо повторяет неправильное использование, замеченное в другом месте, но не понятое или подвергнутое сомнению. Также то, что вы говорите в тексте, неясно и неправильно. Также это ничего не добавляет ко многим ответам уже здесь. (Хотя почти все они довольно бедные.) PS Пожалуйста, уточняйте с помощью правок, а не комментариев.
Филипп

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

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

  • Левое внешнее соединение - левое внешнее соединение даст все строки в A, а также все общие строки в B.

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


1
Это и неправильно, и неясно. Соединение не является пересечением, если таблицы не имеют одинаковые столбцы. Внешние объединения не имеют строк из A или B, если они не имеют одинаковые столбцы, в этом случае не добавляются пустые значения. Вы пытаетесь что-то сказать, но вы этого не говорите. Вы не объясняете правильно или четко.
Филипп

@philipxy: не согласен с вашим утверждением. Join is not an intersection unless the tables have the same columnsНет. Вы можете присоединиться к любым столбцам, которые вам нужны, и, если значение совпадает, они объединятся.
SuicideSheep

Этот комментарий так же неясен, как и ваш ответ. (Я полагаю, что вы можете подумать что-то вроде: набор значений subrow для общих столбцов результата - это пересечение наборов значений subrow для общих столбцов каждого из входных данных; но это не то, что вы написали. не понятно.)
philipxy

Я имел в виду, что соединение - это только пересечение входов, когда это естественное внутреннее соединение входов с одинаковыми столбцами. Вы используете слова «пересечение» и «союз» неправильно.
Philipxy

3

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

Пример:

SELECT
  e1.emp_name,
  e2.emp_salary    
FROM emp1 e1
INNER JOIN emp2 e2
  ON e1.emp_id = e2.emp_id

output1

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

Пример:

SELECT
  e1.emp_name,
  e2.emp_salary    
FROM emp1 e1
FULL OUTER JOIN emp2 e2
  ON e1.emp_id = e2.emp_id

output2

3. Левое внешнее соединение: или просто называется левым соединением. Он возвращает все строки, присутствующие в левой таблице и соответствующие строки из правой таблицы (если есть).

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

присоединяется

Преимущества Joins

  1. Выполняется быстрее.

2
Это верно только тогда, когда таблицы имеют одинаковый набор столбцов. (Это путает внутреннее соединение с пересечением и полное соединение с объединением.) Также «соответствие» не определено. Прочитайте мои другие комментарии.
Philipxy

2

Рассмотрим ниже 2 таблицы:

EMP

empid   name    dept_id salary
1       Rob     1       100
2       Mark    1       300
3       John    2       100
4       Mary    2       300
5       Bill    3       700
6       Jose    6       400

отдел

deptid  name
1       IT
2       Accounts
3       Security
4       HR
5       R&D

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

В основном написано как просто JOIN в SQL-запросах. Он возвращает только совпадающие записи между таблицами.

Узнайте всех сотрудников и имена их отделов:

Select a.empid, a.name, b.name as dept_name
FROM emp a
JOIN department b
ON a.dept_id = b.deptid
;

empid   name    dept_name
1       Rob     IT
2       Mark    IT
3       John    Accounts
4       Mary    Accounts
5       Bill    Security

Как вы видите выше, Joseне выводится из EMP на выходе, так как его dept_id 6не находит соответствия в таблице Department. Аналогично HRи R&Dстроки не распечатываются из отдела таблицы , поскольку они не нашли соответствия в таблице EMP.

Таким образом, INNER JOIN или просто JOIN возвращает только совпадающие строки.

СЛЕДУЮЩЕЕ СОЕДИНЕНИЕ:

Это возвращает все записи из таблицы LEFT и только совпадающие записи из таблицы RIGHT.

Select a.empid, a.name, b.name as dept_name
FROM emp a
LEFT JOIN department b
ON a.dept_id = b.deptid
;

empid   name    dept_name
1       Rob     IT
2       Mark    IT
3       John    Accounts
4       Mary    Accounts
5       Bill    Security
6       Jose    

Таким образом, если вы наблюдаете вышеприведенный вывод, все записи из таблицы LEFT (Emp) печатаются с совпадающими записями из таблицы RIGHT.

HRи R&Dстроки не выводятся из таблицы Department, так как они не нашли соответствия в таблице Emp в dept_id.

Таким образом, LEFT JOIN возвращает ВСЕ строки из левой таблицы и только совпадающие строки из правой таблицы.

Также можете проверить ДЕМО здесь .


2

Общая идея

Пожалуйста , смотрите ответ на Мартина Смита за лучшие illustations и объяснения различных соединений, в том числе и в особенности различия между FULL OUTER JOIN, RIGHT OUTER JOINи LEFT OUTER JOIN.

Эти две таблицы образуют основу для представления JOINниже:

основа

CROSS JOIN

Crossjoin

SELECT *
  FROM citizen
 CROSS JOIN postalcode

Результатом будут декартовы произведения всех комбинаций. Никаких JOINусловий не требуется:

CrossJoinResult

ВНУТРЕННЕЕ СОЕДИНЕНИЕ

INNER JOIN так же, как просто: JOIN

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

SELECT *
  FROM citizen    c
  JOIN postalcode p ON c.postal = p.postal

Результатом будут комбинации, удовлетворяющие требуемому JOINусловию:

InnerJoinResult

ЛЕВЫЕ НАРУЖНЫЕ

LEFT OUTER JOIN такой же как LEFT JOIN

LeftJoin

SELECT *
  FROM citizen         c
  LEFT JOIN postalcode p ON c.postal = p.postal

Результатом будет все, citizenдаже если нет совпадений postalcode. Снова требуется JOINусловие:

LeftJoinResult

Данные для игры

Все примеры были запущены на Oracle 18c. Они доступны на dbfiddle.uk, откуда также пришли скриншоты таблиц.

CREATE TABLE citizen (id      NUMBER,
                      name    VARCHAR2(20),
                      postal  NUMBER,  -- <-- could do with a redesign to postalcode.id instead.
                      leader  NUMBER);

CREATE TABLE postalcode (id      NUMBER,
                         postal  NUMBER,
                         city    VARCHAR2(20),
                         area    VARCHAR2(20));

INSERT INTO citizen (id, name, postal, leader)
              SELECT 1, 'Smith', 2200,  null FROM DUAL
        UNION SELECT 2, 'Green', 31006, 1    FROM DUAL
        UNION SELECT 3, 'Jensen', 623,  1    FROM DUAL;

INSERT INTO postalcode (id, postal, city, area)
                 SELECT 1, 2200,     'BigCity',         'Geancy'  FROM DUAL
           UNION SELECT 2, 31006,    'SmallTown',       'Snizkim' FROM DUAL
           UNION SELECT 3, 31006,    'Settlement',      'Moon'    FROM DUAL  -- <-- Uuh-uhh.
           UNION SELECT 4, 78567390, 'LookoutTowerX89', 'Space'   FROM DUAL;

Размытые границы при игре с JOINиWHERE

CROSS JOIN

CROSS JOINв результате чего строки в качестве общей идеи / INNER JOIN:

SELECT *
  FROM citizen          c
  CROSS JOIN postalcode p
 WHERE c.postal = p.postal -- < -- The WHERE condition is limiting the resulting rows

Использование CROSS JOINдля получения результата LEFT OUTER JOINтребует трюков, таких как добавление в NULLстроку. Это опущено.

ВНУТРЕННЕЕ СОЕДИНЕНИЕ

INNER JOINстановится декартовой продукцией. Это так же, как общая идея / CROSS JOIN:

SELECT *
  FROM citizen    c
  JOIN postalcode p ON 1 = 1  -- < -- The ON condition makes it a CROSS JOIN

Именно здесь внутреннее соединение действительно можно рассматривать как перекрестное соединение с результатами, не соответствующими удаленному условию. Здесь ни одна из полученных строк не удаляется.

Использование INNER JOINдля получения результата LEFT OUTER JOINтакже требует хитростей. Это опущено.

ЛЕВЫЕ НАРУЖНЫЕ

LEFT JOINприводит к строкам как общая идея / CROSS JOIN:

SELECT *
  FROM citizen         c
  LEFT JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN

LEFT JOINприводит к строкам как общая идея / INNER JOIN:

SELECT *
  FROM citizen         c
  LEFT JOIN postalcode p ON c.postal = p.postal
 WHERE p.postal IS NOT NULL -- < -- removed the row where there's no mathcing result from postalcode

Проблемы с диаграммой Венна

Поиск в интернете по изображению "sql join cross inner external" покажет множество диаграмм Венна. Раньше у меня была печатная копия одного на моем столе. Но есть проблемы с представительством.

Диаграмма Венна отлично подходит для теории множеств, где элемент может быть в одном или обоих наборах. Но для баз данных мне кажется, что элемент в одном «наборе» является строкой в ​​таблице и, следовательно, не присутствует ни в каких других таблицах. Нет такой вещи, как одна строка присутствует в нескольких таблицах. Строка уникальна для таблицы.

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

Набор Aпредставляет собой набор слева ( citizenтаблица), а набор B- это набор справа ( postalcodeтаблица) в обсуждении ниже.

CROSS JOIN

Каждый элемент в обоих наборах сопоставляется с каждым элементом в другом наборе, что означает, что нам нужно Aколичество каждого Bэлемента и Bколичество каждого Aэлемента, чтобы правильно представить этот декартово произведение. Теория множеств не создана для нескольких идентичных элементов в наборе, поэтому я считаю, что диаграммы Венна правильно представляют ее непрактично / невозможно. Кажется, что это совсем не UNIONподходит.

Строки различны. Всего UNION7 строк. Но они несовместимы для общего SQLнабора результатов. И это совсем не так CROSS JOIN:

CrossJoinUnion1

Попытка представить это так:

CrossJoinUnion2Crossing

..но теперь это просто выглядит как INTERSECTION, что это, конечно, нет . Кроме того, в этом элементе нет ни INTERSECTIONодного из двух различных наборов. Тем не менее, это очень похоже на результаты поиска, похожие на это:

CrossJoinUnionUnion3

Для справки один результат поиска для CROSS JOINs можно увидеть на Tutorialgateway . Как INTERSECTIONи этот, пуст.

ВНУТРЕННЕЕ СОЕДИНЕНИЕ

Значение элемента зависит от JOINусловия. Это можно представить при условии, что каждая строка становится уникальной для этого условия. Значение id=xверно только для одного ряда. Как только строка в table A( citizen) соответствует нескольким строкам в table B( postalcode) при JOINусловии, результат имеет те же проблемы, что и CROSS JOIN: Строка должна быть представлена ​​несколько раз, и теория множеств на самом деле не создана для этого. Хотя при условии уникальности диаграмма может работать, но имейте в виду, что это JOINусловие определяет размещение элемента на диаграмме. Глядя только на значения JOINусловия с остальной частью ряда только для поездки:

InnerJoinIntersection - заполнено

Это представление полностью расходится при использовании INNER JOINс ON 1 = 1условием, превращающим его в CROSS JOIN.

С self- JOIN, строки на самом деле являются идентичными элементами в обеих таблицах, но представляют таблицы как обе Aи Bне очень подходят. Например , общее само JOINусловие , которое делает элемент Aбудет сопрягать иной элемент в В ON A.parent = B.child, что делает матч с Aчтобы Bна отдельно элементах. Из примеров, которые будут SQLпохожи на это:

SELECT *
  FROM citizen c1
  JOIN citizen c2 ON c1.id = c2.leader

SelfJoinResult

То есть Смит - лидер и Грина, и Дженсена.

НАРУЖНОЕ СОЕДИНЕНИЕ

Опять проблемы начинаются, когда одна строка имеет несколько совпадений со строками в другой таблице. Это дополнительно усложняется тем, что OUTER JOINможет соответствовать пустому набору. Но в теории множеств объединение любого множества Cи пустого множества всегда справедливо C. Пустой набор ничего не добавляет. Представление этого LEFT OUTER JOINобычно просто показывает все, Aчтобы проиллюстрировать, что строки Aвыбираются независимо от того, есть совпадение или нет B. Однако у «совпадающих элементов» есть те же проблемы, что и на иллюстрации выше. Они зависят от состояния. И пустой набор, кажется, забрел к A:

LeftJoinIntersection - заполнено

ГДЕ оговорка - смысл

Нахождение всех строк CROSS JOINсо Смитом и почтовым индексом на Луне:

SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE c.name = 'Smith'
   AND p.area = 'Moon';

Где - результат

Теперь диаграмма Венна не используется для отражения JOIN. Используется только для WHEREпредложения:

куда

... и это имеет смысл.

Когда INTERSECT и UNION имеет смысл

ПЕРЕСЕЧЕНИЕ

Как объяснил, это INNER JOINне совсем INTERSECT. Однако INTERSECTs можно использовать по результатам отдельных запросов. Здесь диаграмма Венна имеет смысл, поскольку элементы отдельных запросов на самом деле являются строками, которые либо принадлежат только одному из результатов, либо обоим. Очевидно, что Intersect будет возвращать результаты только в том случае, если строка присутствует в обоих запросах. Это SQLприведет к тому же ряду, что и приведенный выше WHERE, и диаграмма Венна также будет такой же:

SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE c.name = 'Smith'
INTERSECT
SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE p.area = 'Moon';

UNION

Ан OUTER JOINне а UNION. Однако UNIONработают в тех же условиях INTERSECT, что и возвращают все результаты, объединяющие оба параметра SELECT:

SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE c.name = 'Smith'
UNION
SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE p.area = 'Moon';

что эквивалентно:

SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE c.name = 'Smith'
   OR p.area = 'Moon';

..и дает результат:

Союз - Результат

Также здесь имеет смысл диаграмма Венна:

UNION

Когда это не относится

Важным примечанием является то, что они работают только тогда, когда структура результатов двух SELECT одинакова, что позволяет сравнивать или объединять. Результаты этих двух не позволят это:

SELECT *
  FROM citizen
 WHERE name = 'Smith'
SELECT *
  FROM postalcode
 WHERE area = 'Moon';

.. пытается объединить результаты с UNIONдает

ORA-01790: expression must have same datatype as corresponding expression

Для дальнейшего интереса прочитайте Скажите НЕТ диаграммам Венна при объяснении СОЕДИНЕНИЙ, и соединения sql как диаграмму Венна . Оба также покрывают EXCEPT.


1

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

В основном, чаще всего запросы JOINсводятся к двум случаям:

Для SELECTподмножества данных A:

  • используйте, INNER JOINкогда связанные данные, которые Bвы ищете, ДОЛЖНЫ существовать для каждого проекта базы данных;
  • используйте, LEFT JOINкогда связанные данные, которые Bвы ищете MIGHT или MIGHT NOT, существуют для каждого проекта базы данных.

1

Разница между inner joinи outer joinзаключается в следующем:

  1. Inner joinэто объединение, объединяющее таблицы на основе совпадающих кортежей, тогда outer joinкак объединение, объединяющее таблицы на основе сопоставленного и несопоставленного кортежа.
  2. Inner joinобъединяет совпавшую строку из двух таблиц, в которой пропущены несопоставленные строки, тогда как outer joinобъединяет строки из двух таблиц, и несопоставленные строки заполняются нулевым значением.
  3. Inner joinэто как операция пересечения, тогда как outer joinэто как операция объединения.
  4. Inner joinэто два типа, тогда outer joinкак три типа.
  5. outer joinбыстрее чем inner join.

1
Результат внешнего соединения такой же, как и у внутреннего соединения, но плюс некоторые дополнительные строки, поэтому я понятия не имею, почему вы думаете, что внешнее соединение будет быстрее. И что это за "два типа" внутреннего соединения? Я полагаю, вы имеете в виду полный, левый и правый для внешнего?
Мартин Смит

1
@ M.achaibou Пожалуйста, не вносите изменения, которые вносят ненужные изменения формата. Имена операторов не являются кодом, если они не используются в коде. Пожалуйста, не вносите изменения в смысл сообщения, оставьте комментарий автору. Если у вас нет представителя, тогда подождите. Бывает, что постер одобрил это, но, пожалуйста, не вносите такие изменения PS Внешнее соединение не быстрее внутреннего соединения.
Филипп
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.