[DB] SQL - 조인(JOIN)이란?
JOIN이란?
조인은 두 개 이상의 테이블을 연결해 하나의 결과 집합으로 만들어준다.
조인은 크게 두 가지로 나눌 수 있다.
- 기본 조인
- 두 테이블 간 관계를 기반으로, 데이터를 합치는 방식
- 특수 조인
- 조인 조건이나 목적이 특이하거나, 논리적인 응용이 들어간 조인
기본 JOIN의 종류
조인 종류 | 설명 |
INNER JOIN |
양쪽 테이블에 모두 존재하는 값만 반환 (교집합) |
LEFT OUTER JOIN |
왼쪽 테이블은 모두 출력, 오른쪽은 일치하는 값만 (차집합 포함) |
RIGHT OUTER JOIN |
오른쪽 테이블은 모두 출력, 왼쪽은 일치하는 값만 (차집합 포함) |
FULL OUTER JOIN |
양쪽 모두 출력 + 일치하지 않는 곳은 NULL (합집합) |
아래 테이블 A, B를 대상으로 JOIN에 대해 어떻게 동작하고, 어떤 결과가 나오는지 확인해보자.
- 테이블 A
id | name |
1 | Alice |
2 | Bob |
3 | Charlie |
- 테이블 B
id | age |
2 | 25 |
3 | 30 |
4 | 40 |
INNER JOIN
교집합이라고 생각하면 된다.
양쪽 테이블(A, B)에서 값이 일치하는 행만 반환한다.
예시로 살펴보자.
SELECT A.id, A.name, B.age
FROM A
INNER JOIN B ON A.id = B.id;
- 결과
id | name | age |
2 | Bob | 25 |
3 | Charlie | 30 |
LEFT OUTER JOIN
왼쪽 테이블(A)의 모든 행을 출력하고, 오른쪽 테이블(B)은 일치하는 값만 출력한다.
일치하지 않는다면 NULL로 자동으로 채워진다. (A 기준 차집합을 포함한다.)
아래 예시로 살펴보자.
SELECT A.id, A.name, B.age
FROM A
LEFT JOIN B ON A.id = B.id;
- 결과
id | name | age |
1 | Alice | NULL |
2 | Bob | 25 |
3 | Charlie | 30 |
RIGHT OUTER JOIN
오른쪽 테이블(B)의 모든 행을 출력하고, 왼쪽 테이블(A)은 일치하는 값만 출력한다.
일치하지 않으면 NULL로 채워진다. (B 기준 차집합을 포함한다.)
SELECT A.id, A.name, B.age
FROM A
RIGHT JOIN B ON A.id = B.id;
- 결과
id | name | age |
2 | Bob | 25 |
3 | Charlie | 30 |
4 | NULL | 40 |
FULL OUTER JOIN
양쪽 테이블(A, B)의 모든 행을 출력한다.
일치하지 않는다면 NULL로 채워진다. (합집합)
주의) MySQL은 FULL OUTER JOIN
을 지원하지 않는다.
→ 사용해야 한다면, LEFT JOIN
+ UNION
+ RIGHT JOIN
을 사용하면 구현할 수 있다.
SELECT A.id, A.name, B.age
FROM A
LEFT JOIN B ON A.id = B.id
UNION
SELECT A.id, A.name, B.age
FROM A
RIGHT JOIN B ON A.id = B.id;
- 결과
id | name | age |
1 | Alice | NULL |
2 | Bob | 25 |
3 | Charlie | 30 |
4 | NULL | 40 |
특수 조인
특정 상황에서 데이터 추출을 효율적으로 하거나, 관계가 같은 테이블 내부에 있을 때 사용하는 방식이다.
특수 JOIN의 종류
조인 방식 | 설명 |
SELF JOIN |
같은 테이블을 자기 자신과 조인 (예: 상사-부하 관계) |
EQUI JOIN |
ON 조건에서 등호(=)를 사용하는 가장 일반적인 조인 방식 (INNER JOIN, OUTER JOIN 대부분 해당) |
CROSS JOIN |
모든 행을 서로 조합 (곱집합) → 조건이 없을 때 사용 |
NATURAL JOIN |
같은 이름의 컬럼으로 자동 조인 (가독성 높지만 비추) |
USING(컬럼명) |
ON 대신 같은 컬럼명으로 명시적으로 조인 |
JOIN + 서브쿼리 |
조인 대상이 서브쿼리 (가상의 테이블로 JOIN) |
SELF JOIN
한 테이블을 두 번 사용해 자기 자신과 조인한다.
emp_id | name | manager_id |
1 | Alice | NULL |
2 | Bob | 1 |
3 | Charlie | 1 |
4 | Dave | 2 |
SELECT e1.name AS employee, e2.name AS manager
FROM emp e1
LEFT JOIN emp e2 ON e1.manager_id = e2.emp_id;
- 결과
employee | manager |
Alice | NULL |
Bob | Alice |
Charlie | Alice |
Dave | Bob |
EQUI JOIN
EQUI JOIN
은 ON 조건에서 등호(=) 를 사용하는 가장 기본적인 조인 방식이다. 실제 대부분의 조인은 이 방식이다.
예시:
SELECT A.id, A.name, B.age
FROM A
JOIN B ON A.id = B.id;
- 결과
id | name | age |
2 | Bob | 25 |
3 | Charlie | 30 |
CROSS JOIN
조건 없이 모든 행을 조합해준다. -> A x B (모든 조합)
- 제품 테이블
product |
A |
B |
- 색깔 테이블
color |
Red |
Blue |
SELECT p.product, c.color
FROM product p
CROSS JOIN color c;
- 결과
- 총 2 x 2 = 4개의 결과가 나온게 확인된다.
product | color |
A | Red |
A | Blue |
B | Red |
B | Blue |
NATURAL JOIN
같은 이름의 컬럼을 자동으로 조인해준다. (ON은 생략한다.)
id
라는 공통 컬럼이 없다면 에러가 발생한다.
가독성은 좋으나, 명확하지 않아 실무에서는 잘 사용하지 않는다.
- 학생 테이블
student_id | name |
1 | Alice |
2 | Bob |
- 점수 테이블
student_id | score |
1 | 95 |
2 | 88 |
SELECT *
FROM student
NATURAL JOIN score;
- 결과
student_id | name | score |
1 | Alice | 95 |
2 | Bob | 88 |
JOIN ... USING (컬럼명)
ON
대신 USING
을 사용해서 조인한다.
NATURAL JOIN
과 유사하지만, 명시적이라는 점에서 차이가 있다.
위의 학생, 점수 테이블을 그대로 사용한 예시를 살펴보자.
SELECT name, score
FROM student
JOIN score USING (student_id);
- 결과
name | score |
Alice | 95 |
Bob | 88 |
JOIN + 서브 쿼리
조인 대상이 가상의 테이블인 경우에 사용한다.
서브쿼리를 통해 필터링된 테이블과 조인이 가능해 유연하다.
- EMP 테이블
emp_id | name | dept_id |
1 | Alice | 10 |
2 | Bob | 20 |
- DEPT 테이블
dept_id | dept_name |
10 | HR |
20 | IT |
SELECT e.name, d.dept_name
FROM emp e
JOIN (SELECT * FROM dept WHERE dept_name = 'IT') d
ON e.dept_id = d.dept_id;
- 결과
name | dept_name |
Bob | IT |