채널별 ARPU 와 ARPPU

난이도 보통 · 권장 11분 · 출력 컬럼 channel, users, payers, arpu, arppu
이 문제 직접 풀어보기 →

문제

채널별로 아래 네 가지를 구하세요. users 그 채널의 전체 가입자 수 payers 그중 결제를 한 번이라도 한 유저 수 arpu 결제액 합계 / 전체 가입자 수 (결제 안 한 유저도 분모에 넣습니다) arppu 결제액 합계 / 결제한 유저 수 (결제한 유저만 분모에 넣습니다) · 결제가 한 건도 없는 채널은 arpu, arppu 를 모두 0 으로 출력하세요. · arpu, arppu 는 소수점 둘째 자리까지 반올림합니다. · arpu 내림차순, 같으면 channel 오름차순으로 정렬하세요.
정렬 arpu DESC, channel ASC

쉽게 설명하면

같은 매출을 전교생으로 나누면 ARPU, 돈 낸 애들로만 나누면 ARPPU. 분자는 같고 분모만 다르다.

분자분모
ARPU총 결제액전체 가입자
ARPPU총 결제액결제한 사람

가입자 100명, 결제자 20명, 매출 200만원이면 → ARPU = 2만원, ARPPU = 10만원. 다섯 배 차이가 난다.

이렇게 푼다

  1. 유저 명단 왼쪽에 두고 결제를 붙인다 (LEFT JOIN).
  2. 분모 두 개를 따로 센다 — 전체는 COUNT(DISTINCT u.user_id), 결제자는 COUNT(DISTINCT p.user_id).
  3. 왜 저게 되냐: LEFT JOIN 이라 결제 없는 사람의 p.user_id 는 빈칸이고, COUNT(DISTINCT) 는 빈칸을 안 세기 때문이다.
  4. 각각 나누고 * 1.0, ROUND(…, 2).

이것만 피하면 된다

자세히

묻는 것 · 분모가 다른 두 평균을 한 쿼리에서 만든다. 실무에서 가장 자주 틀리는 지표 쌍이고, 면접에서도 묻는다.

풀이 순서

  1. ARPU 와 ARPPU 는 분자가 같고 분모만 다르다. 분자는 둘 다 결제액 합계, 분모는 ARPU 는 전체 가입자, ARPPU 는 결제 유저.
  2. users LEFT JOIN payments 로 결제 안 한 유저까지 붙인다.
  3. 분모 두 개를 COUNT(DISTINCT u.user_id) 와 COUNT(DISTINCT p.user_id) 로 따로 센다. LEFT JOIN 이라 결제 없는 유저의 p.user_id 는 NULL 이고, COUNT(DISTINCT) 는 NULL 을 안 세므로 자동으로 결제 유저 수가 된다.
  4. * 1.0 을 붙이고 ROUND(..., 2).

정답 (MySQL)

SELECT u.channel,
       COUNT(DISTINCT u.user_id) AS users,
       COUNT(DISTINCT p.user_id) AS payers,
       ROUND(COALESCE(SUM(p.amount), 0) * 1.0
             / NULLIF(COUNT(DISTINCT u.user_id), 0), 2)     AS arpu,
       COALESCE(ROUND(SUM(p.amount) * 1.0
             / NULLIF(COUNT(DISTINCT p.user_id), 0), 2), 0) AS arppu
FROM users u
LEFT JOIN payments p ON p.user_id = u.user_id
GROUP BY u.channel
ORDER BY arpu DESC, u.channel ASC;

함정

이렇게 변형된다

“ARPPU 대신 중앙값”이면 ROW_NUMBER + COUNT() OVER 패턴. “월별 ARPU 추이”면 GROUP BY 월, 채널 로 바꾸되 분모를 그 달의 활성 유저로 둘지 전체 가입자로 둘지를 문제에서 확인하라 — 여기서 정의가 갈린다.

← Q17. 3일 이상 연속 상승 구간 모두 찾기Q19. 한 번도 결제하지 않은 유저 수 →