CASE 문

WAS·2025년 9월 25일
0

SQL

목록 보기
4/7

✅ CASE

  • 데이터 자체를 동적으로 가공하고 새로운 의미를 부여
  • IF ELSE THEN 처럼, 특정조건에 따라 다른 값을 출력하게 하는 SQL의 강력한 조건부 로직
  • 원본 데이터는 건드리지 않고, 비즈니스 로직에 따라 새로운 값을 동적으로 생성

WHEN 조건들 중에서 어느것도 하나도 참이 아닌 경우, ELSE 뒤의 결과를 반환
만약 ELSE 를 생략했는데, 모든 WHEN 조건이 거짓이면 NULL 이 반환됨

💡 위에서 아래 순서로 조건을 평가하며, 먼저 참이되는 WHERE 절을 만나면
THEN의 결과를 반환하고 다른 조건은 보지 않는다

CASE 문의 문법은 다음과 같다

// 문법  (CASE WHEN ELSE END)
CASE 비교대상_컬럼_또는_표현식
 	WHEN1 THEN 결과1
 	WHEN2 THEN 결과2
 	...
 	ELSE 그_외의_경우_결과
END

CASE 문은 크게 단순 CASE 문검색 CASE 문 으로 나뉜다
단순 CASE문 : 표현식의 값에 따라 결과를 다르게 하고 싶을 때 사용

select status , 
		case 
			when status = 'COMPLETED' then '완료'
			when status = 'SHIPPED' then '배송중'
			when status = 'PENDING' then '대기'
			else '알수없음'
		end as status_korean // 별칭부여
from orders;

검색 CASE문 : WHEN 절에 독립적인 조건식을 사용하여 복 잡한 논리를 구현할 때 사용
비교 연산자와 논리 연산자를 사용할 수 있다 (AND OR NOT)

SELECT
 	name,
	price,
 	CASE
 		WHEN price >= 100000 THEN '고가'
 		WHEN price >= 30000 THEN '중가'
 		ELSE '저가'
 	END AS price_label
FROM products;

CASE 문은 SELECT 절 외에도 ORDER BY GROUP BY WHERE 등 다양한 곳에서 사용할 수 있다
만약 상품을 '고가' '중가' '저가' 순으로 정렬하고 싶다고 가정해보자

SELECT
 	name,
 	price,
 	CASE
 		WHEN price >= 100000 THEN '고가'
 		WHEN price >= 30000 THEN '중가'
 		ELSE '저가'
 	END AS price_label
FROM products
ORDER BY
 	CASE
		WHEN price >= 100000 THEN 1 -- 고가: 1
		WHEN price >= 30000 THEN 2 -- 중가: 2
	    ELSE 3 -- 저가: 3
 	END ASC, -- 숫자가 작은 순서대로 정렬 (1순위 정렬 기준)
	price DESC; -- 같은 등급 내에서는 가격 내림차순 (2순위 정렬 기준)

이번엔 CASE 문을 GROUP BY 에 넣은 예시를 확인하자
고객들을 출생 연대에 따라 '1990년대생', '1980년대생', '그 이전 출생'으로 분류하고, 각 그룹에 고객이 총 몇 명씩 있는 조회 라는 문제가 있다고 가정하자

문제를 해결하면 ORDER BY 에서 해결한 것처럼 GROUP BY 뒤에 CASE문을 그대로 넣어줘야한다

SELECT
	 CASE
	 	WHEN YEAR(birth_date) >= 1990 THEN '1990년대생'
	 	WHEN YEAR(birth_date) >= 1980 THEN '1980년대생'
	 	ELSE '그 이전 출생'
 	 END AS birth_decade,
 	 COUNT(*) AS customer_count
FROM users
GROUP BY
 	CASE
 		WHEN YEAR(birth_date) >= 1990 THEN '1990년대생'
 		WHEN YEAR(birth_date) >= 1980 THEN '1980년대생'
 		ELSE '그 이전 출생'
   END;

하지만 CASE문으로 조회한 결과값의 별칭을 GROUP BY 뒤에 넣어줘도 그룹핑이 된다
원래의 SQL 표준 논리적 실행순서에 따르면 GROUP BY 절이 SELECT 절보다 먼저 처리되기 때문에

CASE문으로 조회한 결과값 (birth_decade) 을 GROUP BY 절에 사용할 수 없지만
편의를 위해서 많은 데이터베이스들이 이러한 별칭 사용은 예외적으로 허용하게 해놨다

SELECT
	 CASE
	 	WHEN YEAR(birth_date) >= 1990 THEN '1990년대생'
	 	WHEN YEAR(birth_date) >= 1980 THEN '1980년대생'
	 	ELSE '그 이전 출생'
 	 END AS birth_decade,
 	 COUNT(*) AS customer_count
FROM users
GROUP BY birth_decade

✅ 조건부 집계

  • CASE 문이 집계함수 (SUM, COUNT) 등의 안으로 들어가는 방법

EX) 하나의 쿼리로, 전체 주문 건수와 함께 '결제 완료(COMPLETED)', '배송(SHIPPED)', '주문 대기(PENDING)' 상태의 주문이 각각 몇 건인지 별도의 컬럼으로 나누기

이 문제는 두가지 방법으로 해결할 수 있다

  1. COUNT 안에 CASE 문 작성하기
SELECT
 	COUNT(*) AS total_orders,
 	COUNT(CASE WHEN status = 'COMPLETED' THEN 1 END) AS completed_count,
	COUNT(CASE WHEN status = 'SHIPPED' THEN 1 END) AS shipped_count,
	COUNT(CASE WHEN status = 'PENDING' THEN 1 END) AS pending_count
FROM
 orders
  1. SUM 안에 CASE 문 작성하기
SELECT
 COUNT(*) AS total_orders,
 	SUM(CASE WHEN status = 'COMPLETED' THEN 1 ELSE 0 END) AS completed_count,
 	SUM(CASE WHEN status = 'SHIPPED' THEN 1 ELSE 0 END) AS shipped_count,
 	SUM(CASE WHEN status = 'PENDING' THEN 1 ELSE 0 END) AS pending_count
FROM
 orders;

COUNT 에서 ELSE 0 을 안적은 이유는 COUNT 는 NULL 일 경우 세지 않음
WHEN 이 거짓이면 NULL로 나와서 자동으로 세지 않음
하지만 ELSE 0을 적어버리면 0은 NULL이 아니기 때문에 세버림

profile
우측 상단 햇님모양 클릭하셔서 무조건 야간모드로 봐주세요!!

0개의 댓글