Join
Join
Join 이란
여러 테이블(보통 2개)의 열들을 조합하여 새로운 테이블을 만드는 것. ANSI SQL은 다음과 같이 5가지의 join을 명시.
- Cross join
- Inner join
- Left outer join
- Right outer join
- Full outer join
테이블 예시
다음 두 테이블을 이용해 설명.
- Table A
id | a_name |
---|---|
1 | a1 |
2 | a2 |
NULL | a0 |
- Table B
id | b_name |
---|---|
1 | b1 |
3 | b3 |
NULL | b0 |
Implicit vs Explicit join notation
SQL에서는 조인을 표현하기 위해 다음과 같이 두 가지 방법을 사용.
Explicit join notation:
JOIN
,ON
키워드를 필수로 사용함으로 조인 조건을 명시한 후 조인.Implicit join notation:
FROM
절과WHERE
문을 통해 암시적으로 테이블을 조인.
Cross Join
두 테이블의 카테시안 곱을 반환. 테이블의 행 개수가 각각 n, m개라면 n * m개의 행을 생성.
- Explicit
SELECT *
FROM A CROSS JOIN B
- Implicit
SELECT *
FROM A, B
- Result
A.id | A.a_name | B.id | B.b_name |
---|---|---|---|
1 | a1 | 1 | b1 |
1 | a1 | 3 | b3 |
1 | a1 | NULL | b0 |
2 | a2 | 1 | b1 |
2 | a2 | 3 | b3 |
2 | a2 | NULL | b0 |
NULL | a0 | 1 | b1 |
NULL | a0 | 3 | b3 |
NULL | a0 | NULL | b0 |
Inner Join
두 테이블에서 특정 열의 값이 조인 구문에 맞는 경우 행들을 결합해서 반환.
이론적으로는 두 테이블의 cross join에서 조건에 맞는 행만 반환.
실제로 카테시안 곱을 다 구하는 것은 무리기 때문에 hash join 혹은 sort-merge join 사용
Equi-join, natural join과 같이 더 세부적으로 분류 가능.
Explicit
SELECT *
FROM A
INNER JOIN B ON A.id = B.id
- Implicit
SELECT *
FROM A, B
WHERE A.id = B.id
- Result (두 테이블에서 id가 일치하는 행은 하나뿐)
A.id | A.a_name | B.b_name |
---|---|---|
1 | a1 | b1 |
Inner Join Null
- NULL이 있는 열에 대한 inner join 수행시 NULL은 반환되지 않음. (NULL은 등식을 만족시키지 않기 때문)
- 큰 테이블을 inner join 할 경우 NULL을 포함시키지 않도록 조심해야 함.
- NULL이 포함된 열을 join하면 별도의 필터링을 거치지 않기 때문에 굉장히 비효율적인 연산들이 발생 가능.
- Join 조건을 확인하기 전에 NOT NULL을 통해 NULL을 필터링시키는 방법도 존재.
Equi Join
- 조인 구문에서 등호 연산자만 사용한 조인.
Natural Join
- Equi-join의 특별한 유형
- 두 테이블이 공유하는 열의 값이 같은 행을 결합해 반환.
- 이름이 같은 경우 JOIN되기 때문에 이름 작성에 주의해야 함. (사용 비권장)
- 다음과 같이 사용.
SELECT *
FROM A NATURAL JOIN B;
Outer Join
조인 구문에 맞지 않는 행 역시 반환하는 join. 다음과 같이 세 가지 종류가 존재. Join notation에 대한 표준은 없음.
- Left outer join
- Right outer join
- Full outer join
Left Outer Join
- 위 그림과 같이 A 와 B 테이블을 조인할 시 A 테이블의 모든 행이 반환되는 조인.
- Inner join 결과에 A 테이블의 행 중 조건을 만족하지 않는 행 역시 추가.
- 조건을 만족하지 않는 행에 대한 B 테이블의 열 값은 NULL.
- 다음과 같이 작성. (OUTER 키워드는 필수가 아님.)
SELECT *
FROM A
LEFT OUTER JOIN B ON A.id = B.id
- Result
A.id | A.a_name | B.id | B.b_name |
---|---|---|---|
1 | a1 | 1 | b1 |
2 | a2 | NULL | NULL |
NULL | a0 | NULL | NULL |
Right Outer Join
- Left outer join에서 A와 B의 역할이 바뀐 조인. B 테이블의 모든 행이 반환됨.
SELECT *
FROM A
RIGHT OUTER JOIN B ON A.id = B.id
- Result
A.id | A.a_name | B.id | B.b_name |
---|---|---|---|
1 | a1 | 1 | b1 |
NULL | NULL | 3 | b3 |
NULL | NULL | NULL | b0 |
Full Outer Join
- Left outer join과 Right outer join을 합친 것.
- 두 테이블의 모든 행을 포함.
- 조건을 만족하지 않는 행은 빈 자리에 NULL을 넣음.
- 다음과 같이 사용.
SELECT *
FROM A
FULL OUTER JOIN B ON A.id = B.id
- Result
A.id | A.a_name | B.id | B.b_name |
---|---|---|---|
1 | a1 | 1 | b1 |
2 | a2 | NULL | NULL |
NULL | a0 | NULL | NULL |
NULL | NULL | 3 | b3 |
NULL | NULL | NULL | b0 |
Full Outer Join MySQL
- MySQL등의 DBMS에서는 full outer join을 지원하지 않음.
- 해당 DBMS들은 left outer join과 right outer join을 union 해서 사용.
Self-join
한 테이블에서 자기 자신과 조인시키는 것으로, 테이블을 구분하기 위해서 Alias를 사용해야 함. 다음은 국가가 같은 사원들의 쌍을 반환하는 테이블 예시.
- Employee 테이블
country | name | id |
---|---|---|
Korea | Ain | 1 |
USA | Buzz | 2 |
Korea | Cyu | 3 |
USA | Dash | 4 |
USA | Elo | 5 |
- SQL
SELECT C1.country, C1.id, C1.name, C2.id, C2.name
FROM Employee C1 INNER JOIN Employee C2
ON C1.country = c2.country
WHERE C1.id < C2.id
- Result
country | id | name | id | name |
---|---|---|---|---|
Korea | 1 | Ain | 3 | Cyu |
USA | 2 | Buzz | 4 | Dash |
USA | 2 | Buzz | 5 | Elo |
USA | 4 | Dash | 5 | Elo |