SQLD를 준비하다 보면 JOIN에서 한 번은 막힙니다. INNER, LEFT, RIGHT, FULL 이름은 외웠는데 막상 결과가 몇 행인지 물으면 헷갈리죠. 사실 JOIN은 딱 하나만 이해하면 끝납니다. 두 표에서 짝이 있는 행은 붙이고, 짝이 없는 행은 버릴지 남길지 정한다는 것입니다. 이 글에서는 작은 표 두 개로 네 가지를 한 번에 정리합니다. 아래 결과는 실제로 쿼리를 실행해서 확인한 값입니다.
JOIN은 결국 무엇을 하는 걸까
JOIN은 두 표를 공통 값(보통 기본키와 외래키)으로 이어 붙여 한 줄로 보여 주는 문법입니다. 회원 표와 주문 표를 예로 들겠습니다.
회원(m) 주문(o)
id name oid mid amt
1 철수 101 1 5000
2 영희 102 1 12000
3 민수 103 3 3000
104 9 8000
주문 표의 mid가 회원 표의 id를 가리킵니다. 그림으로 보면 이렇습니다.

철수는 주문이 두 건이라 선이 두 개, 민수는 한 건입니다. 영희는 주문이 없고, 주문 104번은 mid가 9인데 회원 표에 9번 회원이 없습니다. 이렇게 짝이 없는 두 행을 어떻게 다루느냐가 JOIN 종류를 나눕니다.
네 가지 JOIN은 짝 없는 행을 어떻게 다룰까

- INNER JOIN: 짝이 있는 행만 남깁니다. 영희도, 104번 주문도 사라집니다. 결과 3행.
- LEFT OUTER JOIN: 왼쪽(FROM 쪽) 표는 전부 남기고, 짝이 없으면 오른쪽 열을 NULL로 채웁니다. 영희가 NULL과 함께 남습니다. 결과 4행.
- RIGHT OUTER JOIN: 오른쪽 표를 전부 남깁니다. 104번 주문이 회원 이름 NULL로 남습니다. 결과 4행.
- FULL OUTER JOIN: 양쪽 모두 남깁니다. 영희와 104번이 둘 다 나옵니다. 결과 5행.
OUTER라는 단어는 생략해도 됩니다. LEFT JOIN이라고만 써도 같은 뜻입니다.
같은 표로 쿼리를 돌리면 결과가 어떻게 나올까
SELECT m.name, o.oid, o.amt FROM 회원 m LEFT JOIN 주문 o ON m.id = o.mid;
LEFT JOIN 결과는 다음과 같습니다. INNER JOIN이라면 영희 줄만 빠집니다.
name oid amt 철수 101 5000 철수 102 12000 영희 NULL NULL 민수 103 3000
RIGHT JOIN은 영희 줄 대신 NULL, 104, 8000 줄이 생기고, FULL JOIN은 두 줄이 모두 있어 5행이 됩니다.
시험에 자주 나오는 함정 세 가지
1) LEFT JOIN인데 왜 왼쪽 행이 사라질까. 오른쪽 표의 조건을 WHERE에 쓰면 NULL 행이 걸러져 사실상 INNER JOIN이 됩니다.
-- 영희가 사라짐 (결과 2행: 철수 101, 102) ... LEFT JOIN 주문 o ON m.id = o.mid WHERE o.amt >= 5000; -- 영희가 남음 (결과 4행: 철수 101, 102, 영희 NULL, 민수 NULL) ... LEFT JOIN 주문 o ON m.id = o.mid AND o.amt >= 5000;
조건을 ON에 쓰면 “짝을 맺는 조건”이고, WHERE에 쓰면 “다 붙인 뒤 거르는 조건”입니다. 순서가 달라서 결과가 달라집니다.
2) 주문이 없는 회원 찾기. LEFT JOIN 뒤에 오른쪽 기본키가 NULL인 행만 고르면 됩니다.
SELECT m.name FROM 회원 m LEFT JOIN 주문 o ON m.id = o.mid WHERE o.oid IS NULL; -- 결과: 영희
3) COUNT(*)와 COUNT(컬럼)의 차이. 회원별로 세어 보면 영희는 COUNT(*)가 1, COUNT(o.oid)는 0입니다. NULL로 붙은 행도 한 줄이라 COUNT(*)는 세고, 컬럼 COUNT는 NULL을 세지 않기 때문입니다. 주문 건수를 셀 때는 COUNT(o.oid)가 맞습니다.
제 해석: 암기보다 이 순서로 풀면 덜 틀린다
제가 문제를 풀 때 쓰는 순서입니다. 먼저 ON 조건으로 짝 지어지는 선을 그립니다. 다음으로 짝 없는 행이 어느 쪽에 있는지 표시합니다. 마지막으로 LEFT면 왼쪽, RIGHT면 오른쪽, FULL이면 양쪽의 짝 없는 행을 살려 줄 수를 셉니다. 벤 다이어그램은 개념 이해용으로는 좋지만, 한 행이 여러 행과 짝이 되는 경우(철수의 주문 두 건)는 원 그림에 드러나지 않습니다. 줄 수를 묻는 문제에서는 꼭 선을 그려 보는 쪽이 안전합니다.
시험 직전 체크리스트
- INNER는 3행, LEFT와 RIGHT는 4행, FULL은 5행이 되는 이유를 말로 설명할 수 있는가
- 오른쪽 표의 조건을 WHERE에 쓰면 LEFT JOIN이 INNER처럼 동작하는 이유를 아는가
- “짝 없는 행 찾기” 문제에서 IS NULL을 오른쪽 기본키에 거는가
- COUNT(*)와 COUNT(컬럼)이 NULL 행에서 어떻게 다른지 아는가
- DBMS에 따라 문법이 다르다는 점을 기억하는가. 예를 들어 MySQL은 FULL OUTER JOIN을 지원하지 않고, Oracle은 예전 방식의 (+) 표기도 씁니다.
안내: 예시 표는 설명을 위해 직접 만든 가상의 데이터이며, 결과는 SQLite에서 실행해 확인했습니다. 실제 시험 문제와 같지 않을 수 있으니 공식 기출과 함께 학습하세요.