CASE 와 서브쿼리 —
검증할 수 있을 만큼만 가져갑니다
둘 다 깊이 파면 책 한 권씩 나오는 주제입니다. 하지만 우리 목표는 분명해요 — AI 가 만든 SQL 을 읽고 검증할 수 있을 정도. 섹션 3 의 마지막 강의, 딱 거기까지만 가볍게 훑고 강의의 진짜 메인인 모델링으로 넘어갑니다.
이번 섹션의 여정
완료 ✓
완료 ✓
완료 ✓
지금 여기
강의 메인
SELECT 부터 JOIN 뻥튀기 함정까지 달려왔습니다. 마지막으로 두 가지 — CASE 와 서브쿼리 — 만 챙기면 섹션 3 완주입니다.
CASE — 조건에 따라 값을 만든다
프로그래밍 언어의 if-else 와 같습니다. “이 조건이면 이 값, 저 조건이면 저 값” — 기본 형태부터 보세요.
CASE
WHEN 조건1 THEN 값1
WHEN 조건2 THEN 값2
ELSE 기본값
END실제로 써볼게요 — 상품 30개를 가격대로 분류합니다.
SELECT
product_name,
price,
CASE
WHEN price >= 50000 THEN '고가'
WHEN price >= 20000 THEN '중가'
ELSE '저가'
END AS 가격대
FROM
products;| product_name | price | 가격대 |
|---|---|---|
| 라운드 티셔츠 | 19000 | 저가 |
| 슬림핏 청바지 | 49000 | 중가 |
| 후드 집업 | 65000 | 고가 |
| 면 셔츠 | 39000 | 중가 |
| ⋮ | ||
| 패딩 점퍼 | 129000 | 고가 |
테이블에 없는 컬럼을 조회하는 그 자리에서 만들어냅니다. 원본 데이터는 그대로 — 보여줄 때만 분류 라벨이 붙는 거예요.
WHEN 순서 함정 — 위에서부터 평가됩니다
CASE 에서 딱 하나 조심할 게 있습니다. WHEN 은 위에서부터 차례로 평가되고, 처음 맞는 조건 하나만 적용됩니다.
전부 중가에 걸립니다
WHEN price >= 20000 THEN '중가' 가 첫 줄에 있으면 — 129,000원짜리 패딩 점퍼도 “2만 원 이상이긴 하니까” 첫 WHEN 에 걸려 중가 판정. 고가 조건까지 내려가 보지도 않습니다.
범위가 좁은 조건부터
price >= 50000 을 price >= 20000 위에 놓으세요. 위에서 먼저 걸러지니 고가 → 중가 → 저가 순서대로 정확하게 분류됩니다.
CASE + GROUP BY — 동적 분류 통계
방금 만든 가격대 분류를 GROUP BY 와 합치면 — 분류별 집계가 됩니다.
SELECT
CASE
WHEN price >= 50000 THEN '고가'
WHEN price >= 20000 THEN '중가'
ELSE '저가'
END AS 가격대,
COUNT(*) AS 상품수
FROM
products
GROUP BY
가격대;| 가격대 | 상품수 |
|---|---|
| 고가 | 7 |
| 중가 | 17 |
| 저가 | 6 |
CASE + GROUP BY = 동적 분류 통계. 연령대별, 매출 규모별, 등급별 — 실무의 분류 통계가 전부 이 형태입니다. 테이블에 분류 컬럼이 없어도 그 자리에서 만들어 집계하니까요.
MySQL 은 SELECT 에서 만든 별칭(가격대)을 GROUP BY 에서 바로 쓸 수
있습니다. 덕분에 CASE 식을 두 번 안 써도 돼요.
서브쿼리 — 쿼리 안의 쿼리
서브쿼리는 이름 그대로 쿼리 안에 또 다른 쿼리가 들어간 형태입니다. 흐름은 하나예요 — “이 값이 뭔지 먼저 구해두고, 그걸로 다시 조회한다.” 가장 흔한 자리는 WHERE 절 안입니다.
예제 1 — 평균보다 비싼 상품. “평균”이 얼마인지 우리가 직접 구할 필요가 없습니다.
SELECT
product_name,
price
FROM
products
WHERE
price > (
SELECT
AVG(price)
FROM
products
);| product_name | price |
|---|---|
| 슬림핏 청바지 | 49000 |
| 후드 집업 | 65000 |
| 면바지 | 42000 |
| ⋮ | |
| 향수 | 89000 |
“평균”, “최댓값” 같은 계산 값을 직접 구하지 않아도 — SQL 이 안쪽 쿼리를 먼저 계산해서 비교에 씁니다. 안쪽 먼저, 바깥 나중. 이 처리 순서 하나만 기억하세요.
예제 2 — 주문이 있는 회원만. 이번엔 값 하나가 아니라 ID 목록을 안쪽에서 구합니다.
SELECT
member_name
FROM
members
WHERE
member_id IN (
SELECT DISTINCT
member_id
FROM
orders
);| member_name |
|---|
| 김철수 |
| 이영희 |
| 박민수 |
| ⋮ |
| 노수아 |
“주문 테이블에 등장하는 회원 ID 목록 안에 있는 회원만” — 회원 20명 중 주문 이력이 있는 16명만 나옵니다.
이 쿼리는 JOIN 으로도 같은 결과를 낼 수 있어요. 둘 다 정답 — 본인이 읽기 편한 쪽으로 쓰면 됩니다.
예제 3 — 카테고리별 최고가 상품 (참고만). 카테고리마다 다른 기준이 들어가는, 살짝 어려워 보이는 케이스입니다.
SELECT
category_id,
product_name,
price
FROM
products p1
WHERE
price = (
SELECT
MAX(price)
FROM
products p2
WHERE
p2.category_id = p1.category_id
);| category_id | product_name | price |
|---|---|---|
| 1 | 패딩 점퍼 | 129000 |
| 2 | 무선 이어폰 | 89000 |
| 3 | 트러플 오일 | 35000 |
| 4 | 클린 코드 | 35000 |
| 5 | 향수 | 89000 |
AI 에게 “카테고리별 최고가 상품 뽑아줘” 라고 시키세요. 여러분은 결과를 보고 — 카테고리 5개에 한 줄씩, 각 줄이 진짜 그 카테고리의 최고가인지 — 검증할 수 있으면 충분합니다. 그게 이 강의의 방식이에요.
언제 CASE, 언제 서브쿼리?
| 이런 상황이라면 | 꺼낼 도구 |
|---|---|
| 한 컬럼을 조건에 따라 다른 값으로 표시 | CASE |
| 조건에 “평균”, “최댓값” 같은 계산 값이 필요 | 서브쿼리 |
| 분류별 집계 (등급별, 연령대별) | CASE + GROUP BY |
| 다른 테이블에 있는 ID 목록으로 필터 | 서브쿼리 (또는 JOIN) |
AI 한테 SQL 을 시킬 때 — “이런 게 있다”는 감만 있으면 충분합니다. AI 가 CASE 나 서브쿼리를 써서 답을 주면, 오늘 본 처리 순서대로 읽어내면 돼요.
자주 막히는 지점
십중팔구 END 를 빼먹은 경우입니다. CASE 는 여는 키워드와 닫는 키워드가 한
쌍이에요.
END 로 닫기 — 별칭까지 붙이면 END AS 가격대.= 는 한 값하고만 비교할 수 있는데, 서브쿼리가 여러 행을 돌려준 경우입니다.
예제 2처럼 ID 목록이 나오는 자리에는 IN 을 씁니다.
=, 목록을 주면 IN — 비교 연산자를 목록용으로 바꾸세요.SELECT 별칭을 GROUP BY 에 쓰는 건 MySQL 의 편의 기능이라, 일부 DB(SQL Server 등)에서는 허용되지 않습니다.
섹션 3 완주 — 도구함이 갖춰졌습니다
여덟 강의를 모두 달렸습니다. 한 줄로 돌아보면 —
| 챕터 | 내용 |
|---|---|
| 3-1 · 연습 | SELECT 의 본질 |
| 3-2 · 연습 | WHERE — 행 거르기 |
| 3-3 · 연습 | ORDER BY / LIMIT |
| 3-4 · 연습 | GROUP BY — “~별” 사고법 |
| 3-5 · 연습 | HAVING — 그룹 조건 |
| 3-6 · 연습 | JOIN 핵심 |
| 3-7 ⭐ · 연습 | JOIN 뻥튀기 함정 |
| 3-8 (지금) · 연습 | CASE / 서브쿼리 |
이만큼이면 — AI 가 만든 SQL 의 80% 는 검증할 수 있는 도구함이 갖춰진 겁니다. 이 강의가 약속한 바로 그 능력이에요.
섹션 4 — DB 모델링. AI 가 SQL 을 짜주는 시대에 진짜 중요한 능력 — 데이터의 틀을 설계하는 법을 배웁니다. 섹션 3 의 모든 문법이 이 설계 위에서 움직입니다.
수고하셨습니다. 모델링으로 넘어가기 전에 — 오늘 배운 CASE 와 서브쿼리, 연습 문제로 손에 묻히고 가요.