AI 시대 DB 모델링 & SQL 완벽 마스터3-8 CASE / 서브쿼리
테크타니 LEARN — 섹션 03 · SQL 핵심 문법 — 한방 압축

CASE 와 서브쿼리 —
검증할 수 있을 만큼만 가져갑니다

둘 다 깊이 파면 책 한 권씩 나오는 주제입니다. 하지만 우리 목표는 분명해요 — AI 가 만든 SQL 을 읽고 검증할 수 있을 정도. 섹션 3 의 마지막 강의, 딱 거기까지만 가볍게 훑고 강의의 진짜 메인인 모델링으로 넘어갑니다.

난이도쉬움소요6분준비물DBeaver + shop DB위치섹션 3 — 8/8 (마지막)

이번 섹션의 여정

3-1 ~ 3-3

완료 ✓

3-4 ~ 3-5

완료 ✓

3-6 ~ 3-7

완료 ✓

3-8 CASE / 서브쿼리

지금 여기

섹션 4 — DB 모델링

강의 메인

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;
DBeaver — SQL Editor (Ctrl + Enter)
SELECT product_name, price, CASE WHEN price >= 50000 THEN '고가' WHEN price >= 20000 THEN '중가' ELSE '저가' END AS 가격대 FROM products;
product_nameprice가격대
라운드 티셔츠19000저가
슬림핏 청바지49000중가
후드 집업65000고가
면 셔츠39000중가
패딩 점퍼129000고가
30 rows fetched — 테이블에 없던 가격대 컬럼이 그 자리에서 생성
CASE 의 본질

테이블에 없는 컬럼을 조회하는 그 자리에서 만들어냅니다. 원본 데이터는 그대로 — 보여줄 때만 분류 라벨이 붙는 거예요.

WHEN 순서 함정 — 위에서부터 평가됩니다

CASE 에서 딱 하나 조심할 게 있습니다. WHEN 은 위에서부터 차례로 평가되고, 처음 맞는 조건 하나만 적용됩니다.

✕ 작은 조건이 위에 오면

전부 중가에 걸립니다

WHEN price >= 20000 THEN '중가' 가 첫 줄에 있으면 — 129,000원짜리 패딩 점퍼도 “2만 원 이상이긴 하니까” 첫 WHEN 에 걸려 중가 판정. 고가 조건까지 내려가 보지도 않습니다.

✓ 큰 조건을 항상 위에

범위가 좁은 조건부터

price >= 50000price >= 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
  가격대;
DBeaver — SQL Editor (Ctrl + Enter)
SELECT CASE WHEN price >= 50000 THEN '고가' WHEN price >= 20000 THEN '중가' ELSE '저가' END AS 가격대, COUNT(*) AS 상품수 FROM products GROUP BY 가격대;
가격대상품수
고가7
중가17
저가6
상품 30개가 3개 분류로 — 7 + 17 + 6 = 30
실무에서 정말 자주 쓰는 패턴

CASE + GROUP BY = 동적 분류 통계. 연령대별, 매출 규모별, 등급별 — 실무의 분류 통계가 전부 이 형태입니다. 테이블에 분류 컬럼이 없어도 그 자리에서 만들어 집계하니까요.

별칭으로 GROUP BY?

MySQL 은 SELECT 에서 만든 별칭(가격대)을 GROUP BY 에서 바로 쓸 수 있습니다. 덕분에 CASE 식을 두 번 안 써도 돼요.

서브쿼리 — 쿼리 안의 쿼리

서브쿼리는 이름 그대로 쿼리 안에 또 다른 쿼리가 들어간 형태입니다. 흐름은 하나예요 — “이 값이 뭔지 먼저 구해두고, 그걸로 다시 조회한다.” 가장 흔한 자리는 WHERE 절 안입니다.

예제 1 — 평균보다 비싼 상품. “평균”이 얼마인지 우리가 직접 구할 필요가 없습니다.

SELECT
  product_name,
  price
FROM
  products
WHERE
  price > (
    SELECT
      AVG(price)
    FROM
      products
  );
DBeaver — SQL Editor (Ctrl + Enter)
SELECT product_name, price FROM products WHERE price > ( SELECT AVG(price) FROM products );
product_nameprice
슬림핏 청바지49000
후드 집업65000
면바지42000
향수89000
① 안쪽 괄호 먼저 계산: AVG(price) → 39900 · ② 그 값으로 바깥 실행: WHERE price > 39900
10 rows fetched — 평균(39,900원)보다 비싼 상품만
서브쿼리의 핵심

“평균”, “최댓값” 같은 계산 값을 직접 구하지 않아도 — SQL 이 안쪽 쿼리를 먼저 계산해서 비교에 씁니다. 안쪽 먼저, 바깥 나중. 이 처리 순서 하나만 기억하세요.

예제 2 — 주문이 있는 회원만. 이번엔 값 하나가 아니라 ID 목록을 안쪽에서 구합니다.

SELECT
  member_name
FROM
  members
WHERE
  member_id IN (
    SELECT DISTINCT
      member_id
    FROM
      orders
  );
DBeaver — SQL Editor (Ctrl + Enter)
SELECT member_name FROM members WHERE member_id IN ( SELECT DISTINCT member_id FROM orders );
member_name
김철수
이영희
박민수
노수아
16 rows fetched — 주문이 없는 회원 4명은 제외

“주문 테이블에 등장하는 회원 ID 목록 안에 있는 회원만” — 회원 20명 중 주문 이력이 있는 16명만 나옵니다.

JOIN 으로도 됩니다

이 쿼리는 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
  );
DBeaver — SQL Editor (Ctrl + Enter)
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_idproduct_nameprice
1패딩 점퍼129000
2무선 이어폰89000
3트러플 오일35000
4클린 코드35000
5향수89000
5 rows fetched — 카테고리 5개마다 최고가 상품이 하나씩
이 정도까지 직접 짤 필요는 없습니다

AI 에게 “카테고리별 최고가 상품 뽑아줘” 라고 시키세요. 여러분은 결과를 보고 — 카테고리 5개에 한 줄씩, 각 줄이 진짜 그 카테고리의 최고가인지 — 검증할 수 있으면 충분합니다. 그게 이 강의의 방식이에요.

언제 CASE, 언제 서브쿼리?

이런 상황이라면꺼낼 도구
한 컬럼을 조건에 따라 다른 값으로 표시CASE
조건에 “평균”, “최댓값” 같은 계산 값이 필요서브쿼리
분류별 집계 (등급별, 연령대별)CASE + GROUP BY
다른 테이블에 있는 ID 목록으로 필터서브쿼리 (또는 JOIN)
암기하지 마세요

AI 한테 SQL 을 시킬 때 — “이런 게 있다”는 감만 있으면 충분합니다. AI 가 CASE 나 서브쿼리를 써서 답을 주면, 오늘 본 처리 순서대로 읽어내면 돼요.

자주 막히는 지점

① CASE 를 썼더니 syntax error 가 나요

십중팔구 END 를 빼먹은 경우입니다. CASE 는 여는 키워드와 닫는 키워드가 한 쌍이에요.

FIX ▸WHEN ~ THEN 묶음이 끝나면 반드시 END 로 닫기 — 별칭까지 붙이면 END AS 가격대.
② Subquery returns more than 1 row 에러

= 는 한 값하고만 비교할 수 있는데, 서브쿼리가 여러 행을 돌려준 경우입니다. 예제 2처럼 ID 목록이 나오는 자리에는 IN 을 씁니다.

FIX ▸안쪽 쿼리가 값 하나를 주면 =, 목록을 주면 IN — 비교 연산자를 목록용으로 바꾸세요.
③ GROUP BY 가격대 가 다른 DB 에서는 에러래요

SELECT 별칭을 GROUP BY 에 쓰는 건 MySQL 의 편의 기능이라, 일부 DB(SQL Server 등)에서는 허용되지 않습니다.

FIX ▸그 DB 에서는 GROUP BY 에 CASE 식 전체를 반복해서 쓰면 됩니다. MySQL 에서는 별칭으로 OK.

섹션 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 / 서브쿼리
✓ 섹션 3 완주

이만큼이면 — AI 가 만든 SQL 의 80% 는 검증할 수 있는 도구함이 갖춰진 겁니다. 이 강의가 약속한 바로 그 능력이에요.

예고 — 이제부터가 강의의 진짜 메인

섹션 4 — DB 모델링. AI 가 SQL 을 짜주는 시대에 진짜 중요한 능력 — 데이터의 틀을 설계하는 법을 배웁니다. 섹션 3 의 모든 문법이 이 설계 위에서 움직입니다.

수고하셨습니다. 모델링으로 넘어가기 전에 — 오늘 배운 CASE 와 서브쿼리, 연습 문제로 손에 묻히고 가요.

NEXT LESSON3-8 연습 문제

가격대 분류부터 평균 비교까지 — CASE 와 서브쿼리를 shop DB 에서 직접 굴려봅니다.

GO ▸ 연습 문제 풀기