📊 [SQL 프로젝트] 제26장 LEFT JOIN - 주문하지 않은 고객도 보고 싶습니다.
제26장 LEFT JOIN - "주문하지 않은 고객도 보고 싶습니다."
학습 목표
이번 장을 학습하면 다음 내용을 할 수 있습니다.
- LEFT JOIN의 의미를 이해할 수 있다.
- INNER JOIN과 LEFT JOIN의 차이를 설명할 수 있다.
- NULL이 나타나는 이유를 이해할 수 있다.
- 실제 업무에서 LEFT JOIN을 사용하는 상황을 설명할 수 있다.
왜 LEFT JOIN이 필요할까요?
지난 장에서는 고객이 주문한 상품을 조회했습니다.
Customers
↓
Orders
↓
OrderDetails
↓
Products
INNER JOIN을 사용하면
주문한 고객만 조회됩니다.
그런데 회사에서는 이런 질문도 자주 합니다.
"우리 고객 중에서 아직 한 번도 주문하지 않은 사람은 누구인가?"
이 질문은 INNER JOIN으로는 해결할 수 없습니다.
먼저 생각해 봅시다.
다음과 같은 고객이 있다고 가정하겠습니다.
| 고객 |
| 김철수 |
| 이영희 |
| 박민수 |
주문 정보는 다음과 같습니다.
| 주문 고객 |
| 김철수 |
| 박민수 |
INNER JOIN의 결과는?
| 고객 |
| 김철수 |
| 박민수 |
이영희는 사라집니다.
왜냐하면
주문 정보가 없기 때문입니다.
하지만 회사는 무엇을 원할까요?
마케팅 부서에서는
"아직 주문하지 않은 고객에게 할인 쿠폰을 보내자."
고객관리 부서에서는
"가입만 하고 주문하지 않은 고객은 누구지?"
이처럼
주문하지 않은 고객도 매우 중요한 정보입니다.
그래서 LEFT JOIN이 필요합니다.
LEFT JOIN의 의미
LEFT JOIN은
왼쪽 테이블의 모든 데이터를 먼저 가져온 후, 연결되는 데이터가 있으면 붙여 주고, 없으면 NULL을 채운다.
즉,
Customers가 왼쪽이라면
모든 고객이 결과에 나타납니다.
실행 결과 먼저 보기
| 고객명 | 주문번호 |
| Alfreds Futterkiste | 10248 |
| Around the Horn | 10249 |
| ... | ... |
| 새로운 고객 | NULL |
마지막 고객은 아직 주문하지 않았습니다.
하지만 결과에서 사라지지 않습니다.
예제 1. 모든 고객과 주문 조회하기
SELECT Customers.CustomerName,
Orders.OrderID
FROM Customers
LEFT JOIN Orders
ON Customers.CustomerID = Orders.CustomerID;
SQL를 한 줄씩 살펴보기
FROM Customers
모든 고객을 기준으로 시작합니다.
LEFT JOIN Orders
주문이 있으면 연결합니다.
없어도 고객은 그대로 남겨 둡니다.
ON Customers.CustomerID = Orders.CustomerID
고객 번호가 같은 주문을 찾습니다.
INNER JOIN과 비교하기
INNER JOIN
Customers
● 김철수
● 이영희
● 박민수
↓
Orders
● 김철수
● 박민수
↓
결과
김철수
박민수
LEFT JOIN
Customers
● 김철수
● 이영희
● 박민수
↓
Orders
● 김철수
● 박민수
↓
결과
김철수
이영희
박민수
이영희도 그대로 남아 있습니다.
NULL은 왜 나타날까요?
주문이 없는 고객은
주문번호가 존재하지 않습니다.
그래서
| 고객명 | 주문번호 |
| 이영희 | NULL |
처럼 출력됩니다.
NULL은
"데이터가 없다."
라는 의미입니다.
오류가 아닙니다.
예제 2. 주문하지 않은 고객만 찾기
이제 LEFT JOIN의 진짜 힘을 볼 차례입니다.
SELECT Customers.CustomerName
FROM Customers
LEFT JOIN Orders
ON Customers.CustomerID = Orders.CustomerID
WHERE Orders.OrderID IS NULL;
실행 결과
| 고객명 |
| 새로운 고객 |
| 홍길동 |
| 김영수 |
이 고객들은
아직 한 번도 주문하지 않았습니다.
왜 IS NULL을 사용할까요?
LEFT JOIN은
없는 데이터를 NULL로 채웁니다.
따라서
WHERE Orders.OrderID IS NULL
은
주문 정보가 없는 고객만 선택하는 것입니다.
실제 업무에서는?
LEFT JOIN은 생각보다 훨씬 많이 사용됩니다.
예를 들어
- 아직 주문하지 않은 고객 찾기
- 아직 배송되지 않은 주문 찾기
- 아직 담당자가 배정되지 않은 업무 찾기
- 아직 제출하지 않은 학생 찾기
- 아직 결제하지 않은 회원 찾기
처럼
'없는 것'을 찾는 업무에서 자주 사용됩니다.
학생들에게 익숙한 예
학교에서도 같은 원리가 사용됩니다.
학생 명단
| 학생 |
| 민수 |
| 지훈 |
| 서연 |
과제 제출
| 학생 |
| 민수 |
| 서연 |
LEFT JOIN을 하면
| 학생 | 제출 |
| 민수 | O |
| 지훈 | NULL |
| 서연 | O |
지훈은
아직 과제를 제출하지 않았다는 것을
바로 알 수 있습니다.
학생들이 가장 쉽게 이해하는 예입니다.
많이 하는 실수
실수 ①
LEFT JOIN인데
WHERE Orders.OrderID > 0
을 사용한다.
그러면
NULL이 모두 제거됩니다.
결국 INNER JOIN과 비슷한 결과가 됩니다.
실수 ②
NULL을
0이라고 생각한다.
NULL은
0도 아니고
빈 문자열도 아닙니다.
데이터가 없는 상태입니다.
실수 ③
LEFT JOIN과 INNER JOIN의 차이를
결과를 보기 전에 문법으로 외우려고 한다.
문법보다
누가 결과에서 사라지는가?
를 먼저 생각해야 합니다.
한눈에 정리
| JOIN 종류 | 결과 |
| INNER JOIN | 양쪽에 모두 있는 데이터만 |
| LEFT JOIN | 왼쪽은 모두, 오른쪽은 있으면 연결 |
이번 장 핵심 정리
✅ INNER JOIN은 공통 데이터만 조회한다.
✅ LEFT JOIN은 왼쪽 테이블의 모든 데이터를 유지한다.
✅ 연결되는 데이터가 없으면 NULL이 출력된다.
✅ LEFT JOIN은 '없는 데이터'를 찾을 때 가장 강력한 JOIN이다.
연습 문제
기본 문제
① 모든 고객과 주문번호를 조회하시오.
② 주문이 없는 고객도 함께 출력되는지 확인하시오.
응용 문제
① 주문하지 않은 고객만 조회하시오.
② 고객 이름과 주문번호를 출력하시오.
도전 문제
학교 데이터베이스에서
학생(Student)과 과제(Assignment) 테이블이 있다고 가정하자.
과제를 제출하지 않은 학생만 조회하는 SQL의 구조를 작성해 보시오.
(힌트: LEFT JOIN과 IS NULL을 활용해 보세요.)
정답
기본 문제
SELECT Customers.CustomerName,
Orders.OrderID
FROM Customers
LEFT JOIN Orders
ON Customers.CustomerID = Orders.CustomerID;
응용 문제
SELECT Customers.CustomerName
FROM Customers
LEFT JOIN Orders
ON Customers.CustomerID = Orders.CustomerID
WHERE Orders.OrderID IS NULL;