New Skill unlocked!
조건문과 수식을 이용하여 간단한 User Segmentation 수행하기
1. 중요 개념
- User Segmentation
특정 조건에 부합하는 사용자들을 하나의 분류군으로 묶는 것
- Case when
범주별로 다른 계산이나 수식을 적용해야 할 때 사용if를 여러 개 사용한 것과 같은 효과
2. 구조
Case when(조건) then(값 또는 수식)
when(조건) then(값 또는 수식)
...
else (값 또는 수식) end
*else는 선택사항이나, end는 필수
3. Troubleshooting
- 목표 : 10세 이상, 30세 미만의 고객의 나이와 성별로 그룹 나누기 (이름도 같이 출력)
Step 1. 모범답안 보기
select name,
age,
gender,
case when (age between 10 and 19) and gender='male' then "10대 남자"
when (age between 10 and 19) and gender='female' then "10대 여자"
when (age between 20 and 29) and gender='male' then "20대 남자"
when (age between 20 and 29) and gender='female' then "20대 여자" end "그룹"
from customers
where age between 10 and 29
Step 2. 원본 코드리뷰
select name,
age,
gender,
/*where로 이미 범위가 한정돼 있는데, 20대 이상은 age>=20으로 분류하고
20대 이하는 age<20으로 분류하면 되지 않을까?*/
case when (age between 10 and 19) and gender='male' then "10대 남자"
when (age between 10 and 19) and gender='female' then "10대 여자"
when (age between 20 and 29) and gender='male' then "20대 남자"
when (age between 20 and 29) and gender='female' then "20대 여자" end "그룹"
from customers
where age between 10 and 29
Step 3. 코드 1차 최적화 시도 및 Claude에게 리뷰받기
select name,
age,
gender,
case when (age>=20 and gender ='male') then '20대 남성'
when (age>=20 and gender ='female') then '20대 여성'
when (age>=10 and gender = 'male') then '10대 남성'
else '10대 여성' end "그룹",
from customers
where age between 10 and 29
네 교수님. 이번엔 case when을 이용하여 소비자 세그먼트 컬럼을 생성한 결과 하나와, 제가 최적화한 결과를 보여드리겠습니다. 제가 최적화한 방향이 엄밀성이나 가독성 측면에서 원본 코드 대비 더 낫다고 생각하는데, 교수님께서는 어떻게 생각하는지 궁금합니다.
(원본 코드)
(내 코드)
Step 4. 거세게 비난받기
평가:
당신의 코드는 원본보다 훨씬 못합니다. 세 가지 심각한 문제가 있습니다.
문제 1: 논리 오류
age>=20은 20-29세뿐 아니라 30세 이상도 포함합니다. WHERE 절이 10-29세로 제한하므로 이번엔 우연히 작동하지만, WHERE 조건이 바뀌면 즉시 버그가 됩니다. age between 20 and 29가 정확합니다.
문제 2: ELSE의 무분별한 사용
ELSE '10대 여성'은 다음을 모두 10대 여성으로 분류합니다:
age=10, gender='other' age=15, gender=NULL age=19, gender='unknown'
원본은 이런 경우 NULL을 반환하여 데이터 품질 문제를 드러냅니다. 당신 코드는 잘못된 데이터를 숨깁니다.
문제 3: 가독성 저하
연령대 조건(between 20 and 29)을 반복 명시하는 것이 의도를 분명히 합니다. age>=20은 독자에게 "왜 상한이 없지?"라는 의문을 남깁니다.
결론:
최적화는 정확성을 해치지 않는 범위에서만 의미가 있습니다. 당신 코드는 조건이 4개에서 3개로 줄었지만, 엄밀성과 유지보수성을 희생했습니다.
실무에서는 원본 방식이 선호됩니다. ELSE는 "모든 정상 케이스를 명시한 후 예외 처리"에만 사용하십시오.
Step 5. What I've learned
1. 쿼리의 동적 변화
SQL에서는 WHERE절의 조건이 상황에 따라 동적으로 변화할 수 있다는 점을 간과했다. 모범답안에서는 WHERE절의 조건이 바뀌더라도 데이터는 항상 같은 값을 표기하겠지만, 내 코드에서는 WHERE 절의 조건이 바뀌면 조회 결과가 바뀌게 된다.
2. 짧은 글이라고 한눈에 들어오는 건 아니다.
코드의 길이가 짧아졌으므로 가독성이 더 높아졌다고 생각했지만 길이가 짧아진다고 반드시 가독성이 높아지는 것은 아니다.
모범답안에서는 WHERE 조건까지 읽지 않고도 20대와 10대를 성별로 나누어 4개의 세그먼트를 구현한 의도를 빠르게 파악할 수 있지만, 내 코드에서는 그 의도가 다소 불명확하다.
3. 필터가 촘촘하지 않으면 품질 낮은 데이터가 섞여나올 수 있다.
나는 gender 컬럼의 값이 'male'과 'female'로만 구성되어 있을 것이라고 전제했지만, 실제론 그렇지 않은 데이터도 섞여 있을 수도 있다. 쿼리문 내 조건절에서 이를 정확히 명시해주어야 'null', 'unknown'과 같은 예상치 못한 데이터가 조회되는 것을 예방할 수 있다.
+추가 트러블슈팅 : 아래 코드는 무엇이 틀렸을까?
설명 : 주문일자가 평일이면 배달시간이 25분 초과되면 지각이고, 주문일자가 주말이면 30분 초과되면 지각이다.
SELECT order_id,
restaurant_name,
day_of_the_week,
delivery_time,
case when day_of_the_week = 'Weekday' then if(delivery_time<25,'On-Time')
when day_of_the_week = 'Weekend' then if(delivery_time<25,'On-Time')
else 'Late' end '지연여부'
FROM food_orders
정답
문제 : if 함수에 인수를 적게 입력했다.
[if 함수 사용법]
if(조건, 참일 때 값(수식), 거짓일 때 값(수식))
코드를 올바르게 고치면 다음과 같다.
SELECT order_id,
restaurant_name,
day_of_the_week,
delivery_time,
case when day_of_the_week = 'Weekday' then if(delivery_time<25,'On-Time', 'Late')
when day_of_the_week = 'Weekend' then if(delivery_time<25,'On-Time', 'Late') end '지연여부'
FROM food_orders
(번외) 위 Troubleshooting에 대한 Claude 교수님의 설명을 들어보자.
**문제 진단:**
CASE WHEN 내부에서 IF 함수를 **불완전하게** 사용했습니다. IF(조건, 참일 때 값, **거짓일 때 값**)은 3개 인자가 필수인데, 당신은 2개만 제공했습니다.
---
**수정 방안 2가지:**
**방안 1: IF 함수 완성**
SELECT order_id,
restaurant_name,
day_of_the_week,
delivery_time,
CASE
WHEN day_of_the_week = 'Weekday' THEN IF(delivery_time < 25, 'On-Time', 'Late')
WHEN day_of_the_week = 'Weekend' THEN IF(delivery_time < 30, 'On-Time', 'Late')
ELSE 'Late'
END AS '지연여부'
FROM food_orders;
**방안 2: CASE WHEN만 사용 (권장)**
SELECT order_id,
restaurant_name,
day_of_the_week,
delivery_time,
CASE
WHEN day_of_the_week = 'Weekday' AND delivery_time < 25 THEN 'On-Time'
WHEN day_of_the_week = 'Weekend' AND delivery_time < 30 THEN 'On-Time'
ELSE 'Late'
END AS '지연여부'
FROM food_orders;
**추가 지적:**
CASE 안에 IF를 중첩하는 것보다 **CASE WHEN에 AND 조건**을 쓰는 것이 더 명확합니다.
방안 2를 사용하십시오.
'ETC > etc3' 카테고리의 다른 글
| [Java] extends와 implements의 차이 (0) | 2025.12.04 |
|---|---|
| [SQL Exercise] 6. 문자열 데이터 조작하기 CAST로 데이터 타입 변환하기 (0) | 2025.11.28 |
| [나의 개발일지] 4. Spring에 대해서 좀 더 자세히 알아봅시다 (0) | 2025.11.20 |
| [나의 개발일지] 3. Java와 클래스 (0) | 2025.11.18 |
| [SQL Exercise] 4. 필터링, 비교 연산자 (0) | 2025.11.18 |