median_days ASC, channel ASC반 애들 키를 작은 순서로 줄 세우고 딱 가운데 애의 키. 평균이 아니다.
| 인원 | 줄 세운 값 | 중앙값 |
|---|---|---|
| 5명 (홀수) | 1 · 2 · 3 · 4 · 5 | 3번째 = 3 |
| 4명 (짝수) | 1 · 2 · 3 · 4 | 2·3번째 평균 = 2.5 |
홀수면 가운데 하나, 짝수면 가운데 둘의 평균. MySQL 에는 MEDIAN 함수가 없어서 직접 만들어야 한다.
(인원+1)/2 와 (인원+2)/2 두 개를 소수점 버려서 쓴다.FLOOR 를 꼭 씌워라.묻는 것 · MySQL 에 MEDIAN 이 없을 때 직접 만들 줄 아는가.
ROW_NUMBER(), 동시에 COUNT() OVER 로 인원수.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;DATEDIFF(끝, 시작) — MySQL 은 인자 순서가 끝이 먼저다. TIMESTAMPDIFF 와 반대라 헷갈린다.FLOOR((cnt+1)/2) 와 FLOOR((cnt+2)/2) 두 자리를 잡는 게 정석.COUNT(*) 가 아니라 MAX(cnt). WHERE 로 이미 2행만 남았기 때문.“상위 25% 지점”이면 PERCENT_RANK() <= 0.25 또는 NTILE(4)=1.