왜 조인 INNER JOIN LEFT JOIN RIGHT JOIN ON·별칭 📝 문제풀이
◀ 이전 📋 목차 CH 07 ▶
🔗 CHAPTER 06 · 중급

여러 테이블을 이어 붙이는 JOIN

데이터는 보통 여러 테이블에 나뉘어 저장돼요. 사용자는 사용자대로, 주문은 주문대로요. 이걸 공통 열(키)로 연결해서 한 번에 보는 게 JOIN이에요. 이 장에서 INNER·LEFT·RIGHT 세 가지를 확실히 잡아봐요.

🎯 이 장을 끝내면
🧩
왜 조인
왜 데이터를 나눠 놓고 다시 합칠까?
중복을 줄이려고 나눴다가(정규화), 필요할 때 이어서 봐요.

사용자 정보와 주문 정보를 한 테이블에 몰아넣으면 같은 사람 이름이 주문마다 반복돼 낭비되고 관리가 어려워요. 그래서 보통 주제별로 테이블을 나눠 저장해요(정규화). 대신 orders에는 "이 주문이 누구 것인지" 가리키는 외래 키(foreign key) user_id를 둬서, users.id와 연결할 수 있게 해요.

🔤
정규화(normalization) — 같은 데이터가 여기저기 중복되지 않도록, 데이터를 주제별 테이블로 잘게 나눠 저장하는 설계 방식이에요. 중복이 줄어 관리가 쉬워지는 대신, 흩어진 정보를 함께 볼 땐 이 장의 JOIN으로 다시 이어 붙여요. (그래서 정규화와 조인은 짝꿍이에요.)
🔤
기본 키(primary key) — 한 테이블에서 각 행을 유일하게 구별하는 열이에요(값이 중복되지도, 비지도 않아요). 여기선 users.id가 기본 키죠. 방금 나온 외래 키는 바로 이 기본 키를 가리켜서 두 테이블을 잇는 거예요.
users 테이블
idname
1'철수'
2'영희'
3'민수'
orders 테이블
iduser_idproduct
1011'키보드'
1021'마우스'
1032'모니터'
🔑 공통 열(키)로 연결한다 orders.user_idusers.id를 가리키는 외래 키예요. 주문 101user_id1이니, 이건 철수의 주문이죠.
"주문마다 누가 시켰는지 이름을 붙여 보고 싶다" — 이럴 때 두 테이블을 이 공통 열로 이어 붙이는 게 JOIN이에요. 💡 즉 "나눠 저장(정규화) → 필요할 때 키로 이어 보기(조인)"가 관계형 DB의 기본 흐름이에요.
JOIN 외래 키 기본 키 INNER JOIN LEFT JOIN RIGHT JOIN ON NULL 별칭
🧭
이 장의 두 테이블. 앞으로 계속 users(id, name)orders(id, user_id, product)를 예로 써요. 핵심은 orders.user_id = users.id라는 연결 조건 하나예요.
🖼️ 그림으로 보기 — JOIN 세 가지 (벤 다이어그램)
INNER JOIN 양쪽 매칭만 (교집합) LEFT JOIN 왼쪽(users) 전부 + 매칭 RIGHT JOIN 오른쪽(orders) 전부 + 매칭
각 그림에서 왼쪽 원 = users, 오른쪽 원 = orders. 색칠된 부분이 결과에 남아요. INNER는 겹치는 부분만, LEFT는 왼쪽 원 전체(매칭 없으면 오른쪽은 NULL), RIGHT는 오른쪽 원 전체예요.
🔗
INNER JOIN
양쪽에 매칭되는 행만 — INNER JOIN
가장 기본. "둘 다 있는 것만" 남겨요.

INNER JOIN은 두 테이블에서 연결 조건이 맞는(매칭되는) 행만 뽑아 이어 붙여요. ON 뒤에 어떤 열로 연결할지 조건을 적어요.

SELECT *
FROM users
INNER JOIN orders
  ON users.id = orders.user_id;   -- ON: 연결 조건

위 예제 데이터에서, users.idorders.user_id서로 맞는 행만 결과에 나와요. 주문이 있는 철수(1)·영희(2)만 나오고, 주문 없는 민수(3)는 빠져요.

INNER JOIN 결과
users.idnameorders.iduser_idproduct
1'철수'1011'키보드'
1'철수'1021'마우스'
2'영희'1032'모니터'
💡
철수는 주문이 2건이라 결과에 2줄로 나와요. 이렇게 한쪽의 한 행이 다른 쪽 여러 행과 매칭되면 그 수만큼 행이 늘어나요. INNER는 생략하고 그냥 JOIN이라 써도 같아요.
⬅️
LEFT JOIN
왼쪽은 전부 남기는 LEFT JOIN
매칭이 없는 왼쪽 행도 살리고, 오른쪽은 NULL로 채워요.

LEFT JOIN왼쪽 테이블(FROM에 적은 쪽)의 모든 행을 남겨요. 오른쪽에 매칭되는 행이 있으면 이어 붙이고, 없으면 오른쪽 열을 NULL로 채워요. "주문이 없는 사용자까지 전부 보고 싶다"에 딱이에요.

SELECT *
FROM users
LEFT JOIN orders
  ON users.id = orders.user_id;

이번엔 주문 없는 민수(3)도 나와요. 대신 매칭되는 주문이 없어서 orders 쪽 열은 NULL이에요.

LEFT JOIN 결과
users.idnameorders.iduser_idproduct
1'철수'1011'키보드'
1'철수'1021'마우스'
2'영희'1032'모니터'
3'민수'NULLNULLNULL
🕳️
NULL은 "값이 없음"이에요. 빈 문자열이나 0이 아니라 아예 데이터가 비어 있다는 표시예요. LEFT JOIN에서 오른쪽이 안 맞으면 이렇게 NULL이 나오는 게 핵심이에요. (그래서 "주문 없는 사용자 찾기"는 WHERE orders.id IS NULL로 걸러요.)
➡️
RIGHT JOIN
반대로, 오른쪽을 전부 — RIGHT JOIN
방향만 다를 뿐 원리는 LEFT와 똑같아요.

RIGHT JOIN오른쪽 테이블의 모든 행을 남기고, 왼쪽에 매칭이 없으면 왼쪽을 NULL로 채워요. 사실 테이블 순서만 바꾸면 LEFT JOIN과 같은 결과라, 실무에선 LEFT를 훨씬 많이 써요.

SELECT *
FROM users
RIGHT JOIN orders
  ON users.id = orders.user_id;

예제 데이터에선 모든 주문에 주인이 있어서, 위 RIGHT JOIN 결과는 INNER JOIN과 똑같이 3줄이에요(고아 주문이 없으니까요).

종류남기는 행매칭 없을 때
INNER JOIN양쪽 다 매칭되는 행만결과에서 빠짐
LEFT JOIN왼쪽 전부 + 매칭되는 오른쪽오른쪽을 NULL
RIGHT JOIN오른쪽 전부 + 매칭되는 왼쪽왼쪽을 NULL
🔤
CROSS JOIN · FULL OUTER JOIN — 위 셋 말고 조인이 둘 더 있어요. CROSS JOINON 조건 없이 양쪽 행을 모두 짝지어 곱한 결과(왼쪽 3행 × 오른쪽 4행 = 12행)로, 곱집합(카티션 곱, cartesian product)이라 불러요. FULL OUTER JOIN양쪽 전부를 남기고 짝 없는 쪽을 NULL로 채워요(LEFT + RIGHT를 합친 셈이에요). 뒤 문제풀이에 잠깐 나오니 이름만 익혀 두세요.
⚠️
SQLite 등 일부 DB는 예전에 RIGHT JOIN을 지원하지 않았어요. 그래서 방향을 뒤집어 LEFT JOIN으로 쓰는 습관을 들이면 어디서든 안전해요.
🏷️
ON·별칭
ON은 연결 조건, 별칭으로 짧게
쿼리를 읽기 쉽게 다듬는 두 가지 요령이에요.

ON두 테이블을 어떤 열로 연결할지를 정하는 연결 조건이에요. WHERE가 "결과를 거르는" 조건이라면, ON은 "행을 이어 붙이는" 조건이라는 점이 달라요.

🔗
ON
행을 이어 붙이는 연결 조건
vs
🔎
WHERE
이어진 결과를 거르는 조건

테이블 이름이 길면 별칭(alias)을 붙여 짧게 써요. users u, orders o처럼요. 그러면 열을 u.name, o.product로 간결하게 쓸 수 있어요.

SELECT u.name, o.product      -- 별칭으로 간결하게
FROM users AS u
JOIN orders AS o
  ON u.id = o.user_id
WHERE o.product = '키보드';   -- ON으로 이은 뒤 WHERE로 거름
🏷️ 별칭 요령 1. AS는 생략 가능users u처럼 AS 없이 바로 붙여도 돼요.
2. 열 앞에 별칭. 을 — 두 테이블에 같은 이름 열(예: id)이 있을 땐 u.id처럼 어느 테이블 것인지 반드시 밝혀야 해요.
3. 짧고 일관되게users→u, orders→o처럼 첫 글자를 자주 써요. 정리: ON = 잇는 조건, WHERE = 거르는 조건, 별칭 = 짧게 쓰기. 이 셋이면 조인 쿼리가 깔끔해져요.
🧠 이 장 핵심 요약
📝
문제풀이 · 점검
배운 걸 가볍게 점검해봐요
시험이 아니라 "내가 이해했나" 확인용이에요. 틀려도 바로 해설이 나와요.
🧪
문제를 풀면 즉시 정답과 해설이 나오고, 위쪽 바에 점수가 쌓여요. 네 가지 유형(객관식 · O/X · 빈칸 · 쿼리결과)을 섞어 두었어요.
CH 07 🔍 서브쿼리 — 쿼리 안의 쿼리로 한 단계 더 복잡한 조회하기