채널별 pro 비중 (0 나누기)

난이도 보통 · 권장 9분 · 출력 컬럼 channel, paying_users, pro_users, pro_ratio
이 문제 직접 풀어보기 →

문제

채널별로 결제 유저 가운데 pro 플랜을 쓴 적 있는 유저의 비중을 구하세요. channel 채널 paying_users 그 채널에서 결제 이력이 1건 이상인 유저 수 pro_users 그중 pro 플랜 결제가 1건 이상인 유저 수 pro_ratio pro_users / paying_users × 100 (소수점 둘째 자리 반올림) · 모든 채널이 결과에 나와야 합니다. 결제 유저가 한 명도 없는 채널도 포함합니다. · 결제 유저가 0 명인 채널의 pro_ratio 는 NULL 이어야 합니다. 0 이나 에러가 아닙니다. · pro_ratio 내림차순, 같으면 channel 오름차순으로 정렬하세요.
정렬 pro_ratio DESC, channel ASC

쉽게 설명하면

결제한 사람 중에 비싼 요금제 쓴 비율. 결제한 사람이 0명인 채널은 계산이 불가능하니 빈칸이어야 한다.

채널결제 유저pro 유저비중
organic37113035.04
newsletter00NULL

0 ÷ 0 은 '0%' 가 아니다. 계산할 수 없음 이다. 그래서 0 이 아니라 빈칸(NULL)이 맞다. 그리고 그 채널도 결과에 나와야 한다.

이렇게 푼다

  1. 채널을 전부 남긴다 (결제 유저가 0명인 채널도).
  2. 채널별로 결제한 사람 수, 그중 pro 쓴 사람 수를 센다.
  3. pro수 * 100.0 / NULLIF(결제수, 0).

이것만 피하면 된다

자세히

묻는 것 · 분모가 0 이 될 수 있는 상황을 아는가.

풀이 순서

  1. 결제 유저 수와 pro 유저 수를 조건부 DISTINCT 집계로.
  2. 비율 계산에서 분모를 NULLIF(분모, 0) 로 감싼다.

정답 (MySQL)

SELECT u.channel,
       COUNT(DISTINCT p.user_id) AS paying_users,
       COUNT(DISTINCT CASE WHEN p.plan='pro' THEN p.user_id END) AS pro_users,
       ROUND(100.0 * COUNT(DISTINCT CASE WHEN p.plan='pro' THEN p.user_id END)
             / NULLIF(COUNT(DISTINCT p.user_id), 0), 2) AS pro_ratio
FROM users u
LEFT JOIN payments p ON p.user_id = u.user_id
GROUP BY u.channel
ORDER BY pro_ratio DESC, u.channel;

함정

이렇게 변형된다

“환불률”, “쿠폰 사용률” 처럼 모집단이 비어 있을 수 있는 비율 전부.

← Q11. 전 유저 결제 요약 (NULL 처리)Q13. 퍼널 단계별 유저 수와 단계 전환율 →