CodeGym /행동 /SQL SELF /조건식: CASE WHEN ... THEN ... ELSE ... END

조건식: CASE WHEN ... THEN ... ELSE ... END

SQL SELF
레벨 10 , 레슨 0
사용 가능

아마 이미 프로그래밍 언어에서 조건문을 써본 적 있을 거야: if-else, switch-case 같은 거 말이지. SQL에도 조건 처리용 도구가 있어: 바로 CASE 표현식! 이걸로 쿼리 안에서 바로 "조건이 맞으면 이렇게, 아니면 저렇게"를 할 수 있어.

CASE 구문은 특히 NULL 값이 들어올 수 있는 데이터를 다룰 때 진짜 유용해. 문법도 엄청 간단해서, 그냥 치트키 느낌이야. 한 번 볼까?

CASE
    WHEN 조건1 THEN 결과1
    WHEN 조건2 THEN 결과2
    ...
    ELSE 기본_결과
END

딱 봐도 이해되지? "이럴 땐 이렇게, 아니면 저렇게". 외우기도 쉬워: "WHEN은 만약, THEN은 뭐 할지, ELSE는 아무것도 안 맞으면 뭐 할지".

예시: 상품 분류하기

예를 들어 products 테이블에 price 컬럼이 있고, 가격에 따라 상품을 그룹으로 나누고 싶다고 해보자.

id name price
1 Magic Wand 120
2 Potion Set 45
3 Crystal Ball 75
4 Enchanted Map NULL
5 Broomstick 99
6 Spell Book 180
SELECT
    name AS product_name,
    price,
    CASE
        WHEN price IS NULL THEN '알 수 없음'
        WHEN price < 50 THEN '저가'
        WHEN price BETWEEN 50 AND 100 THEN '표준'
        ELSE '프리미엄'
    END AS price_category
FROM products;

여기서 뭐가 일어나냐면?

  1. 상품의 priceNULL이면 카테고리를 '알 수 없음'으로 표시해.
  2. 가격이 50 미만이면 '저가'로 분류해.
  3. 가격이 50~100 사이면 '표준' 카테고리로 들어가.
  4. 나머지는 다 '프리미엄' 상품이야.

결과는 이래:

product_name price price_category
Magic Wand 120 프리미엄
Potion Set 45 저가
Crystal Ball 75 표준
Enchanted Map NULL 알 수 없음
Broomstick 99 표준
Spell Book 180 프리미엄

SQL은 마치 마법사처럼 products 테이블의 각 행을 읽고, 똑똑하게 분류해줘.

CASE WHEN에서 NULL 다루기

데이터에 빠진 값(NULL)이 자주 있는데, 이걸 뭔가로 바꿔줘야 할 때가 많아. 예를 들어 users 테이블에 email 컬럼이 있는데, 이메일 없는 유저는 '입력 안 됨'으로 표시하고 싶다고 해보자.

user_id name email
1 Alex Lin alex@example.com
2 Maria Chi NULL
3 Anna Song anna@magic.com
4 Otto Art NULL
5 John Smith john@wizard.org
SELECT
    user_id,
    name,
    CASE
        WHEN email IS NULL THEN '입력 안 됨'
        ELSE email
    END AS email_address
FROM users;
user_id name email_address
1 Alex Lin alex@example.com
2 Maria Chi 입력 안 됨
3 Anna Song anna@magic.com
4 Otto Art 입력 안 됨
5 John Smith john@wizard.org

SQL이 여기선 샤먼처럼 빈 칸을 채워줘. 이메일이 없으면 '입력 안 됨'으로 바꿔주고, 있으면 그대로 둬.

숫자와 함께 쓰는 조건식

가끔은 값만 바꾸는 게 아니라, 새로운 로직을 만들어야 할 때도 있어. 예를 들어 students 테이블에 score(점수)와 name 컬럼이 있다고 해보자.

name score
Alex Lin 95
Maria Chi 82
Anna Song 48
Otto Art NULL
John Smith 67
Zoe Black 30

학생들을 "우수", "통과", "실패"로 점수에 따라 평가하고 싶어.

SELECT
    name AS student_name,
    score,
    CASE
        WHEN score IS NULL THEN '점수 없음'
        WHEN score >= 90 THEN '우수'
        WHEN score >= 50 THEN '통과'
        ELSE '실패'
    END AS performance_category
FROM students;
student_name score performance_category
Alex Lin 95 우수
Maria Chi 82 통과
Anna Song 48 실패
Otto Art NULL 점수 없음
John Smith 67 통과
Zoe Black 30 실패

SQL이 학생들을 엄격한 시험관처럼 분류해줘: 90점 이상은 "우수", 50점 이상은 "통과". 점수가 부족하면... 뭐, 알지?

그룹핑과 NULL 처리

데이터 그룹핑도 CASE WHEN이 빛을 발하는 분야야. 예를 들어 orders 테이블에서 상태별로 주문 개수를 세고 싶은데, NULL 상태도 포함해야 해.

order_id status
1 Completed
2 Pending
3 NULL
4 Shipped
5 Completed
6 NULL
7 Pending
8 Completed
9 Shipped
10 NULL
SELECT
    CASE
        WHEN status IS NULL THEN '상태 없음'
        ELSE status
    END AS order_status,
    COUNT(*)
FROM orders
GROUP BY 
    CASE
        WHEN status IS NULL THEN '상태 없음'
        ELSE status
    END;

이 쿼리는 NULL 상태를 '상태 없음'으로 바꿔주고, 각 그룹별 주문 개수를 세어줘. 결과는 이래:

order_status count
Completed 3
Pending 2
Shipped 2
상태 없음 3

실전 케이스: CASE WHEN "마술"

예시 1: NULL 고려한 정렬

가끔 NULL 값을 정렬할 때 맨 앞이나 맨 뒤로 보내고 싶을 때가 있어. 예를 들어, 우선순위가 있는 작업은 위에, 우선순위 없는(NULL) 작업은 아래에 표시하고 싶을 때 자주 써.

task_id task_name priority
1 Fix bugs 1
2 Update documentation 3
3 Plan sprint NULL
4 Code review 2
5 Organize meeting NULL
6 Deploy release 1
SELECT
    task_name,
    priority,
    CASE
        WHEN priority IS NULL THEN 1
        ELSE 0
    END AS priority_sort
FROM tasks
ORDER BY priority_sort ASC, priority ASC;

여기선 "가상" 컬럼 priority_sort를 만들어서 NULL 값은 아래로, 나머지는 오름차순 정렬해.

task_name priority priority_sort
Deploy release 1 0
Fix bugs 1 0
Code review 2 0
Update documentation 3 0
Plan sprint NULL 1
Organize meeting NULL 1

예시 2: NULL 고려한 계산

이번엔 orders 테이블에서 주문 총액을 계산하는데, discount 컬럼이 NULL일 수도 있어.

order_id total_price discount
101 100 10
102 200 NULL
103 150 15
104 120 NULL
105 80 5

계산이 깨지지 않게 NULL을 0으로 바꿔야 해.

SELECT 
    order_id,
    total_price,
    discount,
    total_price - 
    CASE
        WHEN discount IS NULL THEN 0
        ELSE discount
    END AS final_price
FROM orders;
order_id total_price discount final_price
101 100 10 90
102 200 NULL 200
103 150 15 135
104 120 NULL 120
105 80 5 75

CASE 마법 덕분에 NULL이 수식 망치는 일은 없어.

orderid = 101: discount = 10. finalprice = 100 - 10 = 90. orderid = 102: discount = NULL. CASE는 0을 반환. finalprice = 200 - 0 = 200. orderid = 103: discount = 15. finalprice = 150 - 15 = 135. orderid = 104: discount = NULL. CASE는 0을 반환. finalprice = 120 - 0 = 120. orderid = 105: discount = 5. finalprice = 80 - 5 = 75.

예시 3: 사용자 상태 표시하기

실무에서 자주 만나는 게 사용자 상태(예: "활성", "대기")를 보여주거나, 데이터가 없음을 표시하는 거야. 예를 들어 users 테이블에 last_login 컬럼이 있고, 마지막 로그인 날짜가 저장돼 있다고 해보자.

user_id name last_login
1 Alex Lin 2024-12-10
2 Maria Chi 2025-04-20
3 Anna Song NULL
4 Otto Art 2025-05-01
5 Liam Park 2025-05-25
SELECT
    user_id,
    name,
    CASE
        WHEN last_login IS NULL THEN '로그인 기록 없음'
        WHEN last_login < CURRENT_DATE - INTERVAL '30 days' THEN '비활성'
        ELSE '활성'
    END AS user_status
FROM users;

이 쿼리로 관리 시스템이 살아나: 로그인 기록 없는 유저는 "로그인 기록 없음", 오래 안 들어온 유저는 "비활성", 나머지는 "활성"!

user_id name user_status
1 Alex Lin 비활성
2 Maria Chi 비활성
3 Anna Song 로그인 기록 없음
4 Otto Art 비활성
5 Liam Park 활성

자주 하는 실수와 예방법

ELSE 빼먹기: ELSE를 안 쓰면, 조건이 하나도 안 맞을 때 SQL은 그냥 NULL을 반환해. 이게 원하는 결과가 아닐 수도 있으니까, 웬만하면 ELSE를 꼭 써주는 게 좋아.

CASE
    WHEN condition THEN result
    -- ELSE '기본값' -- 잊지 마!
END

괄호 없는 복잡한 조건: AND, OR, NOT 등 복잡한 조건이 여러 개면 항상 괄호를 써. 안 그러면 쿼리가 "생각"을 잘못할 수도 있어.

CASE
    WHEN (column1 IS NOT NULL AND column2 > 5) THEN '유효'
    ELSE '무효'
END

NULL 다루기: NULL은 절대 (=)로 비교하면 안 돼. 예를 들어:

CASE
    WHEN column = NULL THEN '아님!' -- 에러!
    WHEN column IS NULL THEN '정답!' -- 이게 맞아.
END
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION