CASE 안에 CASE 트릭

dragonloly·2025년 4월 16일
0

SQL

목록 보기
15/19

언제 사용?

CASE 안에 CASE를 써야 하는 이유는
"어떤 조건을 '하나하나에 대해 검사'한 다음, 그것들을 모아서 최종 판단하려고 할 때"

"일단 각 줄에 대해 조건 판단하고"
"그 판단 결과들로 '모아서' (집계해서) 결론 내고 싶을 때"

각 row에 대해 어떤 조건을 검사해서 1 또는 0 등으로 처리한 후" ➕ "그걸 집계해서 뭔가 최종 판단을 해야 할 때

CASE
    WHEN SUM(
        CASE 
            WHEN '2022-10-16' BETWEEN START_DATE AND END_DATE THEN 1
            ELSE 0 
        END
    ) > 0 
    THEN '대여중'
    ELSE '대여 가능'
END

생각 흐름

"차량 하나당 대여 기록이 여러 개 있는데..."
"그 여러 기록들 중 하나라도 2022-10-16이 포함되어 있으면 '대여중'이라고 하고 싶어."
"그럼 하나하나의 기록에 대해 '그 날짜가 들어 있는지'를 검사해야 하네?"
→ 이게 안쪽 CASE
→ 조건을 만족하면 1, 아니면 0
"그리고 그 1, 0들을 전부 더해서 하나라도 있으면(=합이 1 이상이면) → 대여중!"
→ 이게 바깥쪽 CASE

→ 각 row마다 1 또는 0 계산하고
→ 이걸 SUM으로 더해보면 1+0 = 1
→ 1 이상이니까 → 대여중

예시 1. 학생 점수 예시

-- 평균 60점 이상인 학생이면 '합격'
CASE
  WHEN AVG(
    CASE 
      WHEN SUBJECT = 'Math' THEN SCORE
      ELSE NULL
    END
  ) >= 60 THEN '합격'
  ELSE '불합격'
END

Math 점수만 뽑아서 평균 내고 싶을 때 → 내부 CASE 사용

예시 2. 상품 구매 예시

CASE
  WHEN COUNT(
    CASE 
      WHEN PURCHASE_DATE BETWEEN '2023-01-01' AND '2023-12-31' THEN 1
    END
  ) >= 1 THEN 'VIP 고객'
  ELSE '일반 고객'
END

최근 1년간 구매한 이력이 1개라도 있으면 → VIP로!

예시 3.고객 이탈 감지

"최근 3개월 동안 한 번이라도 로그인한 유저는 '활성', 아니면 '이탈'"

CASE
  WHEN SUM(
    CASE
      WHEN LOGIN_DATE >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH) THEN 1
      ELSE 0
    END
  ) > 0 THEN '활성'
  ELSE '이탈'
END AS USER_STATUS

왜 CASE 안에 CASE?
→ 각 로그인 기록을 보고, 그중 "최근 3개월 안에 한 번이라도 로그인했는지" 판단해야 하니까!
→ 로그인 기록이 여러 건일 수 있으니 SUM으로 모아야 해.

예시 4.불만족 주문 고객 필터링

주문 중 하나라도 '불만족' 리뷰가 있으면 '주의고객

CASE
  WHEN SUM(
    CASE 
      WHEN REVIEW_RATING <= 2 THEN 1
      ELSE 0
    END
  ) > 0 THEN '주의고객'
  ELSE '정상'
END AS CUSTOMER_TYPE

예시 5. 마케팅 타겟 선정

최근 30일 동안 3번 이상 상품 클릭한 사람만 타겟팅

CASE
  WHEN SUM(
    CASE 
      WHEN CLICK_DATE >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) THEN 1
      ELSE 0
    END
  ) >= 3 THEN '타겟'
  ELSE '비타겟'
END AS TARGET_TAG

예시 6. 정기 결제 실패 여부 체크

결제 기록 중 실패가 한 번이라도 있었으면 '리스크고객'

CASE
  WHEN SUM(
    CASE
      WHEN PAYMENT_STATUS = 'FAILED' THEN 1
      ELSE 0
    END
  ) > 0 THEN '리스크고객'
  ELSE '정상고객'
END AS RISK_LEVEL

예시 7. CS센터에서 '클레임' 발생 고객 분류

한 번이라도 '클레임' 문의한 적 있으면 '고위험군'

CASE
  WHEN COUNT(
    CASE 
      WHEN INQUIRY_TYPE = '클레임' THEN 1
    END
  ) > 0 THEN '고위험군'
  ELSE '일반고객'
END AS CS_RISK

요약

이런 경우엔 거의 CASE 안에 CASE + 집계함수(SUM, COUNT 등) 패턴

profile
IT기업에서 운영 기획 담당하고 있습니다 : )

0개의 댓글