В чем разница между левым, правым, внешним и внутренним соединениями?

562

Мне интересно, как дифференцировать все эти разные соединения ...

мили относительного движения
источник
60
из кода
SQLMenace
3
Также зависит от вашего уровня понимания, для кого-то вроде вас эта статья ничего не делает, но для кого-то, кто, возможно, не совсем понимает присоединения, это довольно ясно
SQLMenace
6
Это дубликат stackoverflow.com/questions/419375/sql-join-differences и, без сомнения, других ...
Клет
1
Это мне очень помогло ... проще всего сделать тестовые столы и поиграть с ними. = P
daGrevis

Ответы:

797

Простой пример . Допустим, у вас есть Studentsтаблица и Lockersтаблица. В SQL, первая таблица указывается в объединении, Studentsявляется ЛЕВЫЙ стол, а второй один, Lockersявляется RIGHT стол.

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

Для примера рассмотрим, что у вас 100 учеников , 70 из которых имеют запирающиеся шкафчики. Всего у вас есть 50 шкафчиков , в 40 из которых есть как минимум 1 студент, а в 10 шкафах нет студентов.

INNER JOIN эквивалентно « покажи мне всех учеников со шкафчиками ».
Любые студенты без шкафчиков или любые шкафчики без студентов отсутствуют.
Возвращает 70 строк

LEFT OUTER JOIN будет « показывать мне всех студентов с соответствующими шкафчиками, если они есть ».
Это может быть общий список студентов или может использоваться для идентификации студентов без шкафчика.
Возвращает 100 строк

RIGHT OUTER JOIN будет « показывать мне все шкафчики и студентов, назначенных им, если они есть ».
Это может быть использовано для идентификации шкафчиков, у которых нет назначенных учеников, или шкафчиков, у которых слишком много учеников.
Возвращает 80 строк (список из 70 учеников в 40 шкафчиках плюс 10 шкафчиков без ученика)

FULL OUTER JOIN будет глупым и, вероятно, не очень полезным.
Что-то вроде « покажи мне всех студентов и все шкафчики и сопоставьте их, где вы можете »
Возвращает 110 строк (все 100 студентов, включая тех, у кого нет шкафчиков. Плюс 10 шкафчиков без учеников)

CROSS JOIN также довольно глупо в этом сценарии.
Он не использует связанное lockernumberполе в таблице учеников, так что в итоге вы получите большой список всех возможных парных связей ученик-шкафчик, независимо от того, существует ли он на самом деле.
Возвращает 5000 строк (100 студентов х 50 шкафчиков). Может быть полезно (с фильтрацией) в качестве отправной точки для сопоставления новых учеников с пустыми шкафчиками.

BradC
источник
12
Используя ваш пример, соединение CROSS будет полезно в качестве отправной точки для создания назначений шкафчиков: начните со всех возможных комбинаций, а затем используйте другие критерии для фильтрации результатов из списка.
Джоэл Коухорн
1
Хороший ответ. Я считаю, что Cross Join чаще всего используется для генерации тестовых данных из нескольких строк, когда вам нужно большое количество записей.
Эли
6
FULL OUTER JOINS может быть полезен при поиске потерянных данных или при сравнении разных версий одного и того же набора данных.
Лара Дуган
3
Кросс-соединение, иначе
акартово
3
Я думаю, как вы начинаете свой запрос влияет на результат типа соединения. Например, SELECT * FROM students RIGHT OUTER JOIN lockers...приведет к другому результату, чем SELECT * FROM lockers RIGHT OUTER JOIN students.... Отличный ответ, но хотелось бы, чтобы он обновлялся с полными SQLзапросами
jbmilgrom
141

Существует три основных типа соединения:

  • INNERОбъединение сравнивает две таблицы и возвращает результаты только при наличии совпадения. Записи из первой таблицы дублируются, когда они совпадают с несколькими результатами во второй таблице. Соединения INNER обычно уменьшают наборы результатов, но поскольку записи могут дублироваться, это не гарантируется.
  • CROSSОбъединение сравнивает две таблицы и возвращает все возможные комбинации строк из обеих таблиц. Вы можете получить много результатов от такого рода объединений, которые могут даже не иметь смысла, поэтому используйте их с осторожностью.
  • OUTERОбъединение сравнивает две таблицы и возвращает данные, когда сопоставление доступно или значения NULL в противном случае. Как и в случае INNER join, это будет дублировать строки в одной таблице, когда она будет соответствовать нескольким записям в другой таблице. Объединения OUTER, как правило, увеличивают наборы результатов, поскольку сами по себе не удаляют записи из набора. Вы также должны квалифицировать OUTER соединение, чтобы определить, когда и где добавлять значения NULL:
    • LEFT означает сохранить все записи из 1-й таблицы независимо от того, что и вставлять значения NULL, когда 2-я таблица не совпадает.
    • RIGHT означает обратное: сохранить все записи из 2-й таблицы независимо от того, что они есть, и вставить значения NULL, если 1-я таблица не совпадает.
    • FULL означает сохранить все записи из обеих таблиц и вставить значение NULL в любую из таблиц, если совпадений нет.

Часто вы видите, будет ли OUTERключевое слово опущено в синтаксисе. Вместо этого это будет просто «LEFT JOIN», «RIGHT JOIN» или «FULL JOIN». Это сделано потому, что соединения INNER и CROSS не имеют никакого значения в отношении LEFT, RIGHT или FULL, и поэтому сами по себе этого достаточно для однозначного указания соединения OUTER.

Вот пример того, когда вы можете использовать каждый тип:

  • INNER: Вы хотите вернуть все записи из таблицы «Счета-фактуры» вместе с соответствующими «линиями счетов-фактур». Это предполагает, что каждый действительный Счет-фактура будет иметь по крайней мере одну строку.
  • OUTER: Вы хотите вернуть все записи «InvoiceLines» для конкретного счета-фактуры вместе с соответствующими записями «InventoryItem». Это бизнес, который также продает сервис, так что не все InvoiceLines будут иметь IventoryItem.
  • CROSS: У вас есть таблица цифр с 10 строками, каждая из которых содержит значения от «0» до «9». Вы хотите создать таблицу диапазонов дат, к которой нужно присоединиться, чтобы в результате вы получили одну запись на каждый день в пределах диапазона. Соединяя эту таблицу CROSS с собой несколько раз, вы можете создать столько последовательных целых чисел, сколько вам нужно (если вы начинаете с 10 до 1 степени, каждое соединение добавляет 1 к показателю степени). Затем используйте функцию DATEADD (), чтобы добавить эти значения к базовой дате для диапазона.
Джоэл Коухорн
источник
1
Ницца. Я бы добавил, что обычно, если вы пишете «JOIN», это означает «INNER JOIN».
matpop
47

Есть только 4 вида:

  1. Внутреннее соединение : самый распространенный тип. Выходная строка создается для каждой пары входных строк, соответствующих условиям соединения.
  2. Внешнее левое соединение : то же самое, что и внутреннее соединение, за исключением того, что если есть какая-либо строка, для которой в таблице справа не может быть найдено ни одной соответствующей строки, выводится строка, содержащая значения из таблицы слева, сNULL для каждого значение в таблице справа. Это означает, что каждая строка из таблицы слева появится хотя бы один раз в выходных данных.
  3. Правое внешнее соединение : то же самое, что и левое внешнее соединение, за исключением того, что роли таблиц поменялись местами.
  4. Полное внешнее соединение : комбинация левого и правого внешних соединений. Каждая строка из обеих таблиц появится в выходных данных хотя бы один раз.

«Перекрестное соединение» или «декартово соединение» - это просто внутреннее соединение, для которого не заданы условия соединения, в результате чего выводятся все пары строк.

Спасибо RusselH за указание ПОЛНЫХ объединений, которые я пропустил.

j_random_hacker
источник
1
как насчет полного внешнего соединения и перекрестного соединения (декартово произведение)?
SQLMenace
full - это эквивалент двух внешних объединений
RussellH
25
FULL - это то, что вы получаете, когда вы испортили свое внутреннее соединение, а затем задаете вопрос здесь: «Почему я получаю N ^ 2 строки вместо N»? Тогда все получают CROSS на вас.
Пол Томблин
24

SQL присоединяется к разнице:

Очень просто запомнить:

INNER JOIN показывать только записи, общие для обеих таблиц.

OUTER JOIN все содержимое обеих таблиц объединено, либо они совпадают, либо нет.

LEFT JOIN такой же как LEFT OUTER JOIN - (Выберите записи из первой (самой левой) таблицы с соответствующими записями правой таблицы.)

RIGHT JOINсовпадает с RIGHT OUTER JOIN- (Выбрать записи из второй (самой правой) таблицы с соответствующими записями левой таблицы.)

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

Лакшми
источник
Существует правильный и актуальный способ обозначить круги на диаграмме Венна, но это не так. Круги не являются входными таблицами. Кроме того, результирующие строки не являются входными строками, поэтому ваше описание там неверно. Также это просто не ясно - вы не объясняете «общее для обоих», «совпадающее», «объединенное».
Philipxy
9

Проверьте Join (SQL) в Википедии

  • Внутреннее соединение - с учетом двух таблиц внутреннее соединение возвращает все строки, которые существуют в обеих таблицах
  • соединение left / right (external) - данные две таблицы возвращают все строки, которые существуют в левой или правой таблице вашего объединения, плюс строки с другой стороны будут возвращены, когда предложение join соответствует, или для NULL будет возвращено значение эти столбцы

  • Full Outer - две таблицы возвращают все строки и возвращают пустые значения, когда ни левого, ни правого столбца нет

  • Cross Joins - Декартово соединение и может быть опасно, если его не использовать осторожно

JoshBerke
источник
6

Сделать это более заметным может помочь. Один пример:

Таблица 1:

ID_STUDENT STUDENT_NAME

1               Raony
2               Diogo
3               Eduardo
4               Luiz

Таблица 2:

ID_STUDENT LOCKER

3               l1
4               l2
5               l3

Что я получаю, когда я делаю:

-Inner join of Table 1 and Table 2: 

    - Inner join returns both tables merged only when the key 
      (ID_STUDENT) exists in both tables

    ID_STUDENT       STUDENT_NAME      LOCKER   

        3               Eduardo          l1
        4               Luiz             l2

-Left join of Table 1 and Table 2:

    - Left join merges both tables with all records form table 1, in 
      other words, there might be non-populated fields from table 2

    ID_ESTUDANTE    NOME_ESTUDANTE     LOCKER   

        1               Raony            -
        2               Diogo            -
        3               Eduardo          l1
        4               Luiz             l2

-Right join of table 1 and table 2:

    - Right join merges both tables with all records from table 2, in 
      other words, there might be non-populated fields from table 1

    ID_STUDENT        STUDENT_NAME     LOCKER   

        3               Eduardo          l1
        4               Luiz             l2
        5               -                l3

-Outter join of table 1 and table 2:

    - Returns all records from both tables, in other words, there
      might be non-populated fields either from table 1 or 2.

    ID_STUDENT        STUDENT_NAME     LOCKER   
        1               Raony            -
        2               Diogo            -
        3               Eduardo          l1
        4               Luiz             l2
        5               -                l3
lfvv
источник
4

LEFT JOINи RIGHT JOINявляются типами OUTER JOINс.

INNER JOIN по умолчанию - строки из обеих таблиц должны соответствовать условию соединения.

RussellH
источник
5
Я не могу поверить, что у этого ответа есть много положительных отзывов, и в то же время он настолько неполный.
nbro
Я думаю, что это был лучший ответ на оригинальный вопрос.
РасселH
3

Внутреннее соединение : показывать только строки, когда есть данные из обеих таблиц.

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

Пето Йонатан
источник
2

Сначала вы должны понять, что делает join? Мы соединяем несколько таблиц и получаем конкретный результат из объединенных таблиц. Самый простой способ сделать это - перекрестное соединение .

Допустим, таблица A имеет два столбца A и B. И таблица B содержит три столбца C и D. Если мы применим перекрестное соединение, то получится много бессмысленных строк. Затем мы должны сопоставить, используя первичный ключ, чтобы получить фактические данные.

Слева: он вернет все записи из левой таблицы и сопоставленные записи из правой таблицы.

Справа: он вернется к левому соединению. Он вернет все записи из правой таблицы и сопоставленные записи из левой таблицы.

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

Наружно: И это как союз. Он вернет все доступные записи из обеих таблиц.

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

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

Спасибо

HM Nayem
источник