Разница между INNER JOIN и LEFT SEMI JOIN

85

В чем разница между an INNER JOINи LEFT SEMI JOIN?

Почему в приведенном ниже сценарии я получаю два разных результата?

Набор INNER JOINрезультатов намного больше. Кто-нибудь может объяснить? Я пытаюсь получить имена внутри, table_1которые появляются только в table_2.

SELECT name
FROM table_1 a
    INNER JOIN table_2 b ON a.name=b.name

SELECT name
FROM table_1 a
    LEFT SEMI JOIN table_2 b ON (a.name=b.name)
user3023355
источник
2
Внутреннее соединение достигнет вашей цели. Я никогда не слышал о полусоединении, пока не увидел этот вопрос.
Дэн Бракук,
left semi joinДолжен возвращаться больше строк , чем inner join.
Гордон Линофф,
1
Команда inner joinвернет данные только в том случае, если обе таблицы совпадают. Функция left joinвернет данные из первой таблицы независимо от того, найдена ли соответствующая запись во второй таблице.
j03z
11
@GordonLinoff не обязательно, a LEFT SEMI JOINвернет только одну строку слева, даже если справа есть несколько совпадений. INNER JOINБудет возвращать несколько строк , если есть несколько согласования справа.
D Stanley
1
@ j03z это не может быть правильным. Если цель левого полусоединения - 1) вернуть только информацию в левой таблице (как говорили другие) и 2) вернуть строки из левой таблицы независимо от совпадения (как я думаю, вы говорите), то это только исходная левая таблица - для этого не требуется никакого соединения. Я думаю, что другие должны быть правы, что левое полусоединение 1) возвращает только столбцы из левой таблицы, 2) возвращает только строки, которые имеют совпадение в правой таблице, и 3) возвращает одну строку слева для одного или больше совпадений.
Carl G

Ответы:

126

INNER JOINМожет возвращать данные из столбцов из обеих таблиц, и может дублировать значения записей по обе стороны имеют более чем один матч. A LEFT SEMI JOINможет возвращать только столбцы из левой таблицы и дает по одной каждой записи из левой таблицы, где есть одно или несколько совпадений в правой таблице (независимо от количества совпадений). Это эквивалентно (в стандартном SQL):

SELECT name
FROM table_1 a
WHERE EXISTS(
    SELECT * FROM table_2 b WHERE (a.name=b.name))

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

Я пытаюсь получить имена в таблице_1, которые отображаются только в таблице_2.

Тогда LEFT SEMI JOINподходящий запрос для использования.

Д Стэнли
источник
Действительно ли существует такая вещь, как LEFT SEMI JOIN? Разве это не просто SEMI JOIN? В этом нет никакого смысла RIGHT SEMI JOIN, не так ли?
ErikE
В Hive - да.
D Stanley
1
отличный ответ именно то, что я искал. я бы сформулировал ответ более точно: «... ВНУТРЕННЕЕ СОЕДИНЕНИЕ будет возвращать одну строку для каждой совпадающей строки правой таблицы , в то время как ЛЕВОЕ ПОЛУ СОЕДИНЕНИЕ ...
Barak1731475
2
Противоположным этому является LEFT ANTI JOIN, который фильтрует данные из правой таблицы в левой таблице в соответствии с ключом. Думал, что оставлю этот самородок для кого-нибудь, кто может искать!
shantanusinghal
64

Предположим, есть 2 таблицы TableA и TableB только с 2 столбцами (Id, Data) и следующими данными:

Таблица А:

+----+---------+
| Id |  Data   |
+----+---------+
|  1 | DataA11 |
|  1 | DataA12 |
|  1 | DataA13 |
|  2 | DataA21 |
|  3 | DataA31 |
+----+---------+

ТаблицаB:

+----+---------+
| Id |  Data   |
+----+---------+
|  1 | DataB11 |
|  2 | DataB21 |
|  2 | DataB22 |
|  2 | DataB23 |
|  4 | DataB41 |
+----+---------+

Внутреннее соединение по столбцу Idвернет столбцы из обеих таблиц и только соответствующие записи:

.----.---------.----.---------.
| Id |  Data   | Id |  Data   |
:----+---------+----+---------:
|  1 | DataA11 |  1 | DataB11 |
:----+---------+----+---------:
|  1 | DataA12 |  1 | DataB11 |
:----+---------+----+---------:
|  1 | DataA13 |  1 | DataB11 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB21 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB22 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB23 |
'----'---------'----'---------'

Левое соединение (или левое внешнее соединение) в столбце Idвернет столбцы из обеих таблиц и соответствующие записи с записями из левой таблицы (нулевые значения из правой таблицы):

.----.---------.----.---------.
| Id |  Data   | Id |  Data   |
:----+---------+----+---------:
|  1 | DataA11 |  1 | DataB11 |
:----+---------+----+---------:
|  1 | DataA12 |  1 | DataB11 |
:----+---------+----+---------:
|  1 | DataA13 |  1 | DataB11 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB21 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB22 |
:----+---------+----+---------:
|  2 | DataA21 |  2 | DataB23 |
:----+---------+----+---------:
|  3 | DataA31 |    |         |
'----'---------'----'---------'

Правое соединение (или правое внешнее соединение) в столбце Idвернет столбцы из обеих таблиц и соответствующие записи с записями из правой таблицы (нулевые значения из левой таблицы):

┌────┬─────────┬────┬─────────┐
│ Id │  Data   │ Id │  Data   │
├────┼─────────┼────┼─────────┤
│  1 │ DataA11 │  1 │ DataB11 │
│  1 │ DataA12 │  1 │ DataB11 │
│  1 │ DataA13 │  1 │ DataB11 │
│  2 │ DataA21 │  2 │ DataB21 │
│  2 │ DataA21 │  2 │ DataB22 │
│  2 │ DataA21 │  2 │ DataB23 │
│    │         │  4 │ DataB41 │
└────┴─────────┴────┴─────────┘

Полное внешнее объединение в столбце Idвернет столбцы из обеих таблиц и соответствующие записи с записями из левой таблицы (нулевые значения из правой таблицы) и записи из правой таблицы (нулевые значения из левой таблицы):

╔════╦═════════╦════╦═════════╗
║ Id ║  Data   ║ Id ║  Data   ║
╠════╬═════════╬════╬═════════╣
║  - ║         ║    ║         ║
║  1 ║ DataA11 ║  1 ║ DataB11 ║
║  1 ║ DataA12 ║  1 ║ DataB11 ║
║  1 ║ DataA13 ║  1 ║ DataB11 ║
║  2 ║ DataA21 ║  2 ║ DataB21 ║
║  2 ║ DataA21 ║  2 ║ DataB22 ║
║  2 ║ DataA21 ║  2 ║ DataB23 ║
║  3 ║ DataA31 ║    ║         ║
║    ║         ║  4 ║ DataB41 ║
╚════╩═════════╩════╩═════════╝

Left Semi Join on column Idвернет столбцы только из левой таблицы, а соответствующие записи - только из левой таблицы:

┌────┬─────────┐
│ Id │  Data   │
├────┼─────────┤
│  1 │ DataA11 │
│  1 │ DataA12 │
│  1 │ DataA13 │
│  2 │ DataA21 │
└────┴─────────┘
Абхишек Бансал
источник
Я называл это «ЛЕВОЕ ВНУТРЕННЕЕ соединение».
Аншул Джоши
DISTINCT of A. * из результата INNER JOIN эквивалентен LEFT SEMI JOIN.
Teja
4
Различие не кажется безопасным, предположим, что A содержит две идентичные записи.
Деннис Джахеруддин
Даже если результат будет таким же, использование DISTINCT может иметь более дорогой план по сравнению с EXISTS
manotheshark
32

Пробовал в Hive и получил следующий результат

Таблица 1

1, wqe, ченнаи, индия

2, Стю, Салем, Индия

3, миа, бангалор, индия

4, йепи, нью-йорк, США

Таблица 2

1, wqe, ченнаи, индия

2, Стю, Салем, Индия

3, миа, бангалор, индия

5, chapie, Лос-Анджелес, США

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

ВЫБРАТЬ * ИЗ table1 INNER JOIN table2 ON (table1.id = table2.id);

1 wqe ченнаи индия 1 wqe ченнаи индия

2 стю салем индия 2 стю салем индия

3 миа бангалор индия 3 миа бангалор индия

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

ВЫБРАТЬ * ИЗ table1 LEFT JOIN table2 ON (table1.id = table2.id);

1 wqe ченнаи индия 1 wqe ченнаи индия

2 стю салем индия 2 стю салем индия

3 миа бангалор индия 3 миа бангалор индия

4 йепи Нью-Йорк США NULL NULL NULL NULL

Левое полусоединение

ВЫБРАТЬ * ИЗ table1 LEFT SEMI JOIN table2 ON (table1.id = table2.id);

1 wqe Ченнаи Индия

2 стю салем, индия

3 Миа Бангалор Индия

примечание: отображаются только записи в левой таблице, тогда как для Left Join отображаются обе записи таблицы

Кумар
источник
0

Пытаюсь изобразить диаграммами Венна для лучшего понимания ..

Левое полусоединение: полусоединение возвращает значения из левой части отношения, совпадающей с правой . Это также называется левым полусоединением.

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

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

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

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

user3190018
источник