INNER JOIN과 LEFT SEMI JOIN의 차이점


82

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)

2
내부 조인은 목표를 달성 할 것입니다. 이 질문을보기 전까지는 세미 조인에 대해 들어 본 적이 없습니다.
Dan Bracuk 2014

left semi join보다 많은 행을 반환해야합니다 inner join.
Gordon Linoff

1
inner join두 테이블 사이의 일치가있는 경우에만 데이터를 반환합니다. 두 left join번째 테이블에서 일치하는 레코드가 있는지 여부에 관계없이 첫 번째 테이블에서 데이터를 반환합니다.
j03z 2014

11
@GordonLinoff가 반드시 필요한 것은 아닙니다 LEFT SEMI JOIN. 오른쪽에 여러 일치 항목이 있더라도 a는 왼쪽에서 한 행만 반환합니다. 은 INNER JOIN오른쪽에 다수의 일치가있는 경우 여러 행을 반환합니다.
D Stanley

1
@ j03z 정확할 수 없습니다. 왼쪽 hemi-join의 목적이 1) 왼쪽 테이블의 정보 만 반환하고 (다른 사람들이 말했듯이) 2) 일치 여부에 관계없이 왼쪽 테이블에서 행을 반환하는 것 (내 생각대로)이면 다음과 같습니다. 원래 왼쪽 테이블 만-이를 수행하기 위해 조인이 필요하지 않습니다. 왼쪽 hemi-join이 1) 왼쪽 테이블의 열만 반환하고, 2) 오른쪽 테이블에서 일치하는 행만 반환하고, 3) 하나 또는 더 많은 경기.
Carl G

답변:


121

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반환하는 반면 a 는 오른쪽의 일치하는 행 수에 관계없이 왼쪽 테이블의 행만 반환합니다. 이것이 결과에 다른 수의 행이 표시되는 이유입니다.

table_2에만 나타나는 table_1 내의 이름을 얻으려고합니다.

그런 다음 a LEFT SEMI JOIN는 사용할 적절한 쿼리입니다.


과 같은 것이 정말로 LEFT SEMI JOIN있습니까? 그냥 SEMI JOIN아닌가? 에 대한 의미 RIGHT SEMI JOIN가 없습니까?
ErikE

에서 하이브 , 예.
D Stanley

1
내가 찾던 것에 대한 훌륭한 대답. 대답을 더 정확하게 표현하겠습니다. "... INNER JOIN은 오른쪽 테이블의 각 일치하는 행에 대해 한 행을 반환하는 반면 LEFT SEMI JOIN ...
Barak1731475

2
그 반대는 키에 따라 왼쪽 테이블의 오른쪽 테이블에서 데이터를 필터링하는 LEFT ANTI JOIN입니다. 찾고있는 누군가를 위해 여기에이 너겟을 남겨 두겠다고 생각 했어!
shantanusinghal

63

2 개의 열 (Id, Data)과 다음 데이터 만있는 TableA 및 TableB 테이블이 2 개 있다고 가정합니다.

TableA :

+----+---------+
| 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은 테이블의 열과 왼쪽 테이블의 레코드와 일치하는 레코드 (오른쪽 테이블의 Null 값 )를 반환합니다.

.----.---------.----.---------.
| 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은 테이블의 열과 오른쪽 테이블의 레코드와 일치하는 레코드 (왼쪽 테이블의 Null 값 )를 반환합니다.

┌────┬─────────┬────┬─────────┐
│ 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 은 테이블의 열과 왼쪽 테이블의 레코드 (오른쪽 테이블의 Null 값) 및 오른쪽 테이블의 레코드 (왼쪽 테이블의 Null 값)와 일치하는 레코드를 모두 반환합니다.

╔════╦═════════╦════╦═════════╗
║ 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 JoinId 은 왼쪽 테이블에서만 열 을 반환하고 왼쪽 테이블에서만 일치하는 레코드를 반환합니다.

┌────┬─────────┐
│ Id │  Data   │
├────┼─────────┤
│  1 │ DataA11 │
│  1 │ DataA12 │
│  1 │ DataA13 │
│  2 │ DataA21 │
└────┴─────────┘

저는 이것을 "LEFT INNER Join"이라고 부르 곤했습니다.
Anshul Joshi

INNER JOIN 결과에서 A. *의 DISTINCT는 LEFT SEMI JOIN과 동일합니다.
Teja

4
Distinct는 안전하지 않은 것 같습니다. A에 두 개의 동일한 레코드가 있다고 가정합니다.
Dennis Jaheruddin

결과가 동일하더라도 DISTINCT를 사용하면 EXISTS에 비해 비용이 더 많이들 수 있습니다
manotheshark

32

Hive에서 시도하고 아래 출력을 얻었습니다.

1 번 테이블

1, wqe, 첸나이, 인도

2, stu, salem, 인도

3, 미아, 방갈로르, 인도

4, yepie, newyork, 미국

표 2

1, wqe, 첸나이, 인도

2, stu, salem, 인도

3, 미아, 방갈로르, 인도

5, chapie, 로스 엔젤스, 미국

내부 조인

SELECT * FROM table1 INNER JOIN table2 ON (table1.id = table2.id);

1 wqe 첸나이 인도 1 wqe 첸나이 인도

2 스투 살렘 인도 2 스투 살렘 인도

3 미아 방갈로르 인도 3 미아 방갈로르 인도

왼쪽 조인

SELECT * FROM table1 LEFT JOIN table2 ON (table1.id = table2.id);

1 wqe 첸나이 인도 1 wqe 첸나이 인도

2 스투 살렘 인도 2 스투 살렘 인도

3 미아 방갈로르 인도 3 미아 방갈로르 인도

4 yepie newyork USA NULL NULL NULL NULL

왼쪽 세미 조인

SELECT * FROM table1 LEFT SEMI JOIN table2 ON (table1.id = table2.id);

1 Wqe 첸나이 인도

2 스투 살렘 인도

3 미아 방갈로르 인도

참고 : 왼쪽 테이블의 레코드 만 표시되는 반면 왼쪽 조인의 경우 두 테이블 레코드가 모두 표시됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.