
문제
https://leetcode.com/problems/confirmation-rate/description/
문제 설명
- 각 사용자의 확인율(confirmation rate) 을 계산하라.
- Signups : 모든 가입자 (user_id, 가입 시각)
- Confirmations : 각 가입자가 보낸 “확인 요청” 기록
- action 값은 'confirmed' 또는 'timeout'
- 확인율 = confirmed 개수 / 전체 요청 개수
- 확인 요청이 없는 사용자의 경우 → 확인율은 0.00
- 결과는 소수점 둘째 자리까지 반올림
정답 코드
SELECT s.user_id,
CASE WHEN c.action IS NULL THEN 0.00
ELSE ROUND(SUM(c.action = "confirmed")/COUNT(*),2)
END AS confirmation_rate
FROM signups s LEFT JOIN confirmations c ON s.user_id = c.user_id
GROUP BY s.user_id
개선점
- CASE WHEN c.action IS NULL은 잘못된 위치
- GROUP BY 이후 집계 함수(SUM, COUNT)를 쓸 때
→ CASE는 그룹 전체에 대해 한 번만 적용되지 않음 - 그래서 일부 DB에서는 이 코드가 정상 작동하더라도, 로직상으로는 “한 행만 NULL이면 전체가 0 처리”될 수 있음
→ IFNULL() 이 훨씬 안전하고 직관적
- GROUP BY 이후 집계 함수(SUM, COUNT)를 쓸 때
- COUNT(*) 대신 COUNT(c.action) 사용
- COUNT(*)는 NULL도 포함해 세기 때문에, LEFT JOIN 결과에서 Confirmations가 전혀 없는 사용자도 1로 계산될 수 있음
- 반면, COUNT(c.action)은 NULL은 세지 않으므로 → 요청이 없을 경우 0으로 정확히 계산됨
- 문자열 리터럴은 'confirmed'로 작성
- MySQL은 " "를 문자열로 인식하지만, 표준 SQL에서는 ' '이 맞음 → LeetCode나 다른 SQL엔진에서의 이식성을 고려하면 ' '을 쓰는 게 좋음
개선된 코드
SELECT
s.user_id,
ROUND(
IFNULL(SUM(c.action = 'confirmed') / COUNT(c.action), 0),
2
) AS confirmation_rate
FROM Signups s LEFT JOIN Confirmations c ON s.user_id = c.user_id
GROUP BY s.user_id
코드 설명
| LEFT JOIN | 모든 가입자 유지 (확인 요청 없는 사용자도 포함) |
| SUM(c.action = 'confirmed') | MySQL에서는 조건이 참이면 1, 거짓이면 0 → confirmed 개수 |
| COUNT(c.action) | 전체 요청 개수 |
| IFNULL(..., 0) | 요청이 전혀 없는 경우 → 0으로 설정 |
| ROUND(..., 2) | 두 자리 소수로 반올림 |
| GROUP BY s.user_id | 사용자별 계산 |
'코딩 테스트 연습 > [프로그래머스][리트코드] MySQL' 카테고리의 다른 글
| 1251. Average Selling Price (0) | 2025.10.16 |
|---|---|
| 620. Not Boring Movies (0) | 2025.10.14 |
| -- 9월 프로젝트 집중 기간 -- (0) | 2025.08.31 |
| 570. Managers with at Least 5 Direct Reports (4) | 2025.08.29 |
| 1280. Students and Examinations (2) | 2025.08.28 |