채널별 첫 결제까지 일수의 중앙값

난이도 어려움 · 권장 15분 · 출력 컬럼 channel, payers, median_days
이 문제 직접 풀어보기 →

문제

결제 경험이 있는 유저만 대상으로, 가입일부터 첫 결제일까지 걸린 일수의 채널별 중앙값을 구하세요. · MySQL 8에는 MEDIAN 함수가 없습니다. · 대상 인원이 짝수면 가운데 두 값의 평균입니다. · 중앙값 오름차순, 같으면 channel 오름차순으로 정렬하세요.
정렬 median_days ASC, channel ASC

쉽게 설명하면

반 애들 키를 작은 순서로 줄 세우고 딱 가운데 애의 키. 평균이 아니다.

인원줄 세운 값중앙값
5명 (홀수)1 · 2 · 3 · 4 · 53번째 = 3
4명 (짝수)1 · 2 · 3 · 42·3번째 평균 = 2.5

홀수면 가운데 하나, 짝수면 가운데 둘의 평균. MySQL 에는 MEDIAN 함수가 없어서 직접 만들어야 한다.

이렇게 푼다

  1. 채널 안에서 값을 작은 순서로 번호를 매긴다 (1, 2, 3 …).
  2. 그 채널의 전체 인원 수도 같은 줄에 같이 붙여 둔다.
  3. 가운데 번호만 남긴다 — (인원+1)/2 와 (인원+2)/2 두 개를 소수점 버려서 쓴다.
  4. 남은 값의 평균을 낸다.

이것만 피하면 된다

자세히

묻는 것 · MySQL 에 MEDIAN 이 없을 때 직접 만들 줄 아는가.

풀이 순서

  1. 유저별 첫 결제일 → 가입일과의 차이(일수).
  2. 채널 안에서 일수 오름차순으로 ROW_NUMBER(), 동시에 COUNT() OVER 로 인원수.
  3. 가운데 위치만 남긴다. 홀수면 1개, 짝수면 2개.
  4. 남은 값을 AVG 하면 짝수 평균까지 한 번에 처리된다.

정답 (MySQL)

WITH f AS (
  SELECT p.user_id, u.channel,
         DATEDIFF(MIN(p.paid_date), u.signup_date) AS d
  FROM payments p JOIN users u ON u.user_id = p.user_id
  GROUP BY p.user_id, u.channel, u.signup_date
),
r AS (
  SELECT channel, d,
         ROW_NUMBER() OVER (PARTITION BY channel ORDER BY d) AS rn,
         COUNT(*)     OVER (PARTITION BY channel)            AS cnt
  FROM f
)
SELECT channel, MAX(cnt) AS payers, AVG(d) AS median_days
FROM r
WHERE rn IN (FLOOR((cnt + 1) / 2), FLOOR((cnt + 2) / 2))
GROUP BY channel
ORDER BY median_days, channel;

함정

이렇게 변형된다

“상위 25% 지점”이면 PERCENT_RANK() <= 0.25 또는 NTILE(4)=1.

← Q5. 월별 매출 분해 (신규/기존/복귀)Q7. 월별 플랜 업그레이드 / 다운그레이드 →