SQL OUTER JOIN이란?
SQL에서 JOIN은 두 개 이상의 테이블을 연결해서 데이터를 조회할 때 사용하는 문법입니다. 그중 OUTER JOIN은 한쪽 테이블에는 데이터가 있지만, 다른 테이블에는 일치하는 데이터가 없을 때도 결과에 포함시키는 JOIN 방식입니다.
이전 글에서 다룬 INNER JOIN은 두 테이블에서 조건이 일치하는 데이터만 조회합니다. 반면 OUTER JOIN은 조건이 일치하지 않는 데이터도 함께 확인할 수 있습니다.
실무에서는 단순히 매칭된 데이터만 보는 것이 아니라, 누락된 데이터나 아직 연결되지 않은 데이터를 찾아야 하는 경우가 많습니다. 예를 들어 회원은 가입했지만 주문을 한 번도 하지 않은 회원을 찾거나, 상품은 등록되어 있지만 아직 판매되지 않은 상품을 확인하는 경우가 있습니다.
이런 상황에서 사용하는 대표적인 문법이 LEFT JOIN과 RIGHT JOIN입니다.
LEFT JOIN이란?
LEFT JOIN은 왼쪽 테이블의 데이터를 기준으로 조회하는 JOIN 방식입니다.
기본 개념은 다음과 같습니다.
왼쪽 테이블의 데이터는 모두 가져오고, 오른쪽 테이블에서 조건이 일치하는 데이터가 있으면 함께 가져옵니다. 조건이 일치하지 않는 경우 오른쪽 테이블의 값은 NULL로 표시됩니다.
기본 문법은 다음과 같습니다.
SELECT 컬럼명
FROM 테이블1
LEFT JOIN 테이블2
ON 테이블1.공통컬럼 = 테이블2.공통컬럼;
여기서 테이블1이 왼쪽 테이블입니다. 따라서 LEFT JOIN은 테이블1의 데이터를 기준으로 결과를 만듭니다.
LEFT JOIN 예제
다음과 같은 회원 테이블과 주문 테이블이 있다고 가정해보겠습니다.
MEMBER 테이블
| member_id | name |
|---|---|
| 1 | 김민수 |
| 2 | 이지은 |
| 3 | 박현우 |
ORDERS 테이블
| order_id | member_id | product |
|---|---|---|
| 101 | 1 | 노트북 |
| 102 | 2 | 키보드 |
회원은 3명이지만 주문 테이블에는 1번 회원과 2번 회원의 주문만 있습니다. 3번 회원인 박현우는 아직 주문을 하지 않았습니다.
이때 모든 회원과 주문 정보를 함께 보고 싶다면 LEFT JOIN을 사용할 수 있습니다.
SELECT
m.member_id,
m.name,
o.product
FROM member m
LEFT JOIN orders o
ON m.member_id = o.member_id;
결과는 다음과 같습니다.
| member_id | name | product |
|---|---|---|
| 1 | 김민수 | 노트북 |
| 2 | 이지은 | 키보드 |
| 3 | 박현우 | NULL |
결과를 보면 주문 내역이 없는 박현우도 조회됩니다. 대신 주문 상품에 해당하는 product 값은 NULL로 표시됩니다.
이것이 LEFT JOIN의 핵심입니다.
왼쪽 테이블인 member의 데이터는 모두 가져오고, 오른쪽 테이블인 orders에 일치하는 데이터가 없으면 NULL로 채웁니다.
RIGHT JOIN이란?
RIGHT JOIN은 오른쪽 테이블의 데이터를 기준으로 조회하는 JOIN 방식입니다.
기본 개념은 다음과 같습니다.
오른쪽 테이블의 데이터는 모두 가져오고, 왼쪽 테이블에서 조건이 일치하는 데이터가 있으면 함께 가져옵니다. 조건이 일치하지 않는 경우 왼쪽 테이블의 값은 NULL로 표시됩니다.
기본 문법은 다음과 같습니다.
SELECT 컬럼명
FROM 테이블1
RIGHT JOIN 테이블2
ON 테이블1.공통컬럼 = 테이블2.공통컬럼;
여기서 테이블2가 오른쪽 테이블입니다. 따라서 RIGHT JOIN은 테이블2의 데이터를 기준으로 결과를 만듭니다.
RIGHT JOIN 예제
이번에는 상품 테이블과 주문 테이블을 예로 들어보겠습니다.
PRODUCT 테이블
| product_id | product_name |
|---|---|
| 10 | 노트북 |
| 20 | 키보드 |
ORDERS 테이블
| order_id | product_id |
|---|---|
| 101 | 10 |
| 102 | 20 |
| 103 | 30 |
주문 테이블에는 product_id = 30인 주문이 있지만, 상품 테이블에는 30번 상품 정보가 없습니다.
이때 주문 테이블의 모든 주문을 기준으로 상품 정보를 조회하고 싶다면 RIGHT JOIN을 사용할 수 있습니다.
SELECT
p.product_name,
o.order_id,
o.product_id
FROM product p
RIGHT JOIN orders o
ON p.product_id = o.product_id;
결과는 다음과 같습니다.
| product_name | order_id | product_id |
|---|---|---|
| 노트북 | 101 | 10 |
| 키보드 | 102 | 20 |
| NULL | 103 | 30 |
오른쪽 테이블인 orders의 데이터는 모두 조회됩니다. 하지만 product_id = 30에 해당하는 상품 정보가 product 테이블에 없기 때문에 product_name은 NULL로 표시됩니다.
LEFT JOIN과 RIGHT JOIN 차이
LEFT JOIN과 RIGHT JOIN의 차이는 기준 테이블이 어디인지입니다.
| 구분 | LEFT JOIN | RIGHT JOIN |
|---|---|---|
| 기준 테이블 | 왼쪽 테이블 | 오른쪽 테이블 |
| 기준 테이블 데이터 | 모두 조회 | 모두 조회 |
| 매칭되지 않는 값 | 오른쪽 컬럼이 NULL | 왼쪽 컬럼이 NULL |
| 사용 빈도 | 높음 | 상대적으로 낮음 |
LEFT JOIN은 왼쪽 테이블을 기준으로 결과를 만들고, RIGHT JOIN은 오른쪽 테이블을 기준으로 결과를 만듭니다.
사실 두 문법은 테이블의 위치만 바꾸면 같은 결과를 만들 수 있습니다.
예를 들어 다음 쿼리는 회원을 기준으로 주문 정보를 조회하는 LEFT JOIN입니다.
SELECT
m.name,
o.product
FROM member m
LEFT JOIN orders o
ON m.member_id = o.member_id;
같은 결과를 RIGHT JOIN으로 작성하면 다음과 같습니다.
SELECT
m.name,
o.product
FROM orders o
RIGHT JOIN member m
ON o.member_id = m.member_id;
두 쿼리는 기준 테이블이 member라는 점에서 같은 결과를 만들 수 있습니다. 다만 첫 번째 쿼리가 훨씬 직관적입니다.
그래서 실무에서는 RIGHT JOIN보다 LEFT JOIN을 더 많이 사용합니다.
실무에서 LEFT JOIN을 더 많이 쓰는 이유
실무에서는 대부분 기준이 되는 테이블을 먼저 작성하고, 필요한 정보를 뒤에 붙이는 방식으로 쿼리를 작성합니다.
예를 들어 회원 목록을 기준으로 주문 정보를 붙이고 싶다면 다음처럼 작성합니다.
FROM member m
LEFT JOIN orders o
ON m.member_id = o.member_id
이 구조는 읽기 쉽습니다.
“회원을 기준으로 주문 정보를 붙인다”는 흐름이 자연스럽기 때문입니다.
반면 같은 결과를 RIGHT JOIN으로 작성하면 테이블 순서가 반대로 되어 쿼리를 읽는 사람이 헷갈릴 수 있습니다.
그래서 특별한 이유가 없다면 RIGHT JOIN보다는 LEFT JOIN을 사용하는 것이 좋습니다.
LEFT JOIN으로 주문하지 않은 회원 찾기
LEFT JOIN은 누락된 데이터를 찾을 때 매우 유용합니다.
예를 들어 회원 중에서 주문을 한 번도 하지 않은 사람을 찾고 싶다고 가정해보겠습니다.
회원 테이블에는 모든 회원이 있고, 주문 테이블에는 주문한 회원만 있습니다.
이때 LEFT JOIN을 사용하면 모든 회원을 기준으로 주문 정보를 붙일 수 있습니다.
SELECT
m.member_id,
m.name,
o.order_id
FROM member m
LEFT JOIN orders o
ON m.member_id = o.member_id;
이 결과에서 주문하지 않은 회원은 o.order_id가 NULL로 나옵니다.
따라서 주문하지 않은 회원만 조회하려면 다음처럼 작성할 수 있습니다.
SELECT
m.member_id,
m.name
FROM member m
LEFT JOIN orders o
ON m.member_id = o.member_id
WHERE o.order_id IS NULL;
이 쿼리는 실무에서 매우 자주 사용됩니다.
특히 다음과 같은 상황에서 활용할 수 있습니다.
- 주문 이력이 없는 회원 찾기
- 아직 배정되지 않은 직원 찾기
- 등록은 되었지만 판매되지 않은 상품 찾기
- 결제 정보가 없는 신청자 찾기
- 매칭되지 않은 데이터 검증하기
LEFT JOIN과 IS NULL 조합은 데이터 누락을 찾을 때 꼭 알아두어야 하는 패턴입니다.
LEFT JOIN과 WHERE 조건 사용 시 주의할 점
LEFT JOIN을 사용할 때 가장 많이 하는 실수는 오른쪽 테이블 조건을 WHERE절에 잘못 작성하는 것입니다.
예를 들어 모든 회원을 조회하되, 주문 상태가 완료인 주문 정보만 보고 싶다고 가정해보겠습니다.
아래 쿼리를 보겠습니다.
SELECT
m.name,
o.order_id,
o.status
FROM member m
LEFT JOIN orders o
ON m.member_id = o.member_id
WHERE o.status = '완료';
이 쿼리는 겉으로 보면 문제가 없어 보입니다. 하지만 실제로는 LEFT JOIN의 의미가 약해질 수 있습니다.
왜냐하면 WHERE o.status = '완료' 조건이 적용되면서 주문 정보가 없는 회원, 즉 o.status가 NULL인 회원은 결과에서 제외되기 때문입니다.
결과적으로 INNER JOIN처럼 동작할 수 있습니다.
이런 경우에는 조건을 ON절에 넣는 것이 더 적절할 수 있습니다.
SELECT
m.name,
o.order_id,
o.status
FROM member m
LEFT JOIN orders o
ON m.member_id = o.member_id
AND o.status = '완료';
이렇게 작성하면 회원은 모두 조회하고, 주문 정보 중에서 상태가 완료인 데이터만 연결합니다. 주문이 없거나 완료 주문이 없는 회원은 주문 정보가 NULL로 표시됩니다.
이 차이는 실무에서 매우 중요합니다.
정리하면 다음과 같습니다.
WHERE에 오른쪽 테이블 조건을 쓰면 매칭되지 않은 행이 제외될 수 있음ON에 조건을 쓰면 기준 테이블 데이터는 유지하면서 연결 조건을 제한할 수 있음
INNER JOIN과 LEFT JOIN 차이
INNER JOIN과 LEFT JOIN도 자주 비교됩니다.
| 구분 | INNER JOIN | LEFT JOIN |
|---|---|---|
| 기준 | 양쪽 모두 일치하는 데이터 | 왼쪽 테이블 전체 |
| 매칭되지 않는 데이터 | 제외 | 포함 |
| NULL 발생 | 거의 없음 | 발생 가능 |
| 주요 목적 | 일치하는 데이터 조회 | 기준 데이터 전체 조회 |
예를 들어 회원과 주문 테이블이 있을 때, 주문한 회원만 보고 싶다면 INNER JOIN을 사용하면 됩니다.
SELECT
m.name,
o.product
FROM member m
INNER JOIN orders o
ON m.member_id = o.member_id;
반대로 주문 여부와 상관없이 모든 회원을 보고 싶다면 LEFT JOIN을 사용해야 합니다.
SELECT
m.name,
o.product
FROM member m
LEFT JOIN orders o
ON m.member_id = o.member_id;
초보자는 이 차이를 명확히 이해해야 합니다.
INNER JOIN은 조건이 맞는 데이터만 가져오고, LEFT JOIN은 왼쪽 테이블을 기준으로 모두 가져옵니다.
RIGHT JOIN은 언제 사용할까?
RIGHT JOIN은 오른쪽 테이블을 기준으로 전체 데이터를 조회해야 할 때 사용할 수 있습니다.
하지만 실무에서는 RIGHT JOIN을 자주 사용하지 않습니다. 이유는 대부분의 RIGHT JOIN 쿼리를 테이블 순서만 바꿔서 LEFT JOIN으로 표현할 수 있기 때문입니다.
예를 들어 다음 RIGHT JOIN 쿼리가 있다고 가정해보겠습니다.
SELECT
m.name,
o.product
FROM orders o
RIGHT JOIN member m
ON o.member_id = m.member_id;
이 쿼리는 다음 LEFT JOIN으로 바꿀 수 있습니다.
SELECT
m.name,
o.product
FROM member m
LEFT JOIN orders o
ON m.member_id = o.member_id;
둘은 같은 결과를 만들 수 있지만, 두 번째 쿼리가 훨씬 읽기 쉽습니다.
그래서 SQL을 처음 공부하는 단계라면 RIGHT JOIN을 많이 쓰기보다, LEFT JOIN을 확실히 이해하는 것이 더 중요합니다.
LEFT JOIN 사용 예시
1. 모든 회원과 주문 내역 조회
SELECT
m.member_id,
m.name,
o.order_id,
o.product
FROM member m
LEFT JOIN orders o
ON m.member_id = o.member_id;
회원은 모두 조회하고, 주문 내역이 있으면 함께 표시합니다.
2. 주문하지 않은 회원 조회
SELECT
m.member_id,
m.name
FROM member m
LEFT JOIN orders o
ON m.member_id = o.member_id
WHERE o.order_id IS NULL;
주문 테이블에 매칭되는 데이터가 없는 회원만 조회합니다.
3. 모든 상품과 판매 내역 조회
SELECT
p.product_id,
p.product_name,
o.order_id
FROM product p
LEFT JOIN orders o
ON p.product_id = o.product_id;
상품은 모두 조회하고, 판매된 상품은 주문 정보까지 함께 표시합니다.
4. 판매되지 않은 상품 조회
SELECT
p.product_id,
p.product_name
FROM product p
LEFT JOIN orders o
ON p.product_id = o.product_id
WHERE o.order_id IS NULL;
상품 목록에는 있지만 아직 주문되지 않은 상품을 찾을 수 있습니다.
LEFT JOIN 사용 시 주의사항
1. 기준 테이블을 먼저 정해야 한다
LEFT JOIN을 사용할 때는 어떤 테이블을 기준으로 전체 데이터를 보고 싶은지 먼저 정해야 합니다.
회원 전체를 보고 싶다면 member 테이블을 왼쪽에 둡니다.
FROM member m
LEFT JOIN orders o
상품 전체를 보고 싶다면 product 테이블을 왼쪽에 둡니다.
FROM product p
LEFT JOIN orders o
기준 테이블을 잘못 잡으면 원하는 결과가 나오지 않을 수 있습니다.
2. NULL 값을 고려해야 한다
LEFT JOIN은 매칭되지 않는 데이터를 NULL로 표시합니다. 따라서 결과를 해석할 때 NULL의 의미를 정확히 이해해야 합니다.
예를 들어 주문 정보가 NULL이라고 해서 회원 정보가 잘못된 것은 아닙니다. 단지 해당 회원의 주문 내역이 없다는 뜻입니다.
3. WHERE 조건 위치를 조심해야 한다
오른쪽 테이블 조건을 WHERE절에 작성하면 매칭되지 않은 데이터가 제외될 수 있습니다.
기준 테이블의 모든 데이터를 유지하고 싶다면 조건을 ON절에 넣어야 하는 경우가 많습니다.
정리
LEFT JOIN과 RIGHT JOIN은 SQL의 대표적인 OUTER JOIN 문법입니다. 두 문법 모두 한쪽 테이블의 데이터를 기준으로 결과를 조회할 때 사용합니다.
LEFT JOIN은 왼쪽 테이블을 기준으로 전체 데이터를 가져오고, 오른쪽 테이블에 일치하는 값이 없으면 NULL로 표시합니다. 반대로 RIGHT JOIN은 오른쪽 테이블을 기준으로 전체 데이터를 가져오고, 왼쪽 테이블에 일치하는 값이 없으면 NULL로 표시합니다.
하지만 실무에서는 RIGHT JOIN보다 LEFT JOIN을 더 많이 사용합니다. 대부분의 RIGHT JOIN은 테이블 순서를 바꾸면 LEFT JOIN으로 표현할 수 있고, LEFT JOIN이 쿼리를 읽는 흐름도 더 자연스럽기 때문입니다.
초보자가 반드시 기억해야 할 핵심은 다음과 같습니다.
SELECT 컬럼명
FROM 기준테이블
LEFT JOIN 연결테이블
ON 기준테이블.공통컬럼 = 연결테이블.공통컬럼;
LEFT JOIN은 기준 테이블의 데이터를 모두 유지하면서 다른 테이블의 정보를 붙이는 방식입니다. 매칭되지 않는 데이터는 NULL로 표시됩니다.
SQL을 공부할 때 INNER JOIN과 LEFT JOIN의 차이를 정확히 이해하면 JOIN 문제의 대부분을 풀 수 있습니다. 특히 데이터 분석이나 실무 쿼리 작성에서는 주문하지 않은 회원, 판매되지 않은 상품, 배정되지 않은 데이터처럼 누락된 값을 찾는 경우가 많기 때문에 LEFT JOIN은 반드시 익숙해져야 하는 핵심 문법입니다.
