[목차]
- 막힌 문제 : CTR구하기
- 질문 : 100이 아니라 100.0을 곱해야하는 이유? / 정수 나눗셈 결과가 0일 때
- 답변 : 정수 나눗셈 문제
- 오늘의 배움
App Clickthrough Rate | Facebook SQL Interview Question
Facebook SQL Interview Question: Write a query to calculate the click-through rate for each app.
datalemur.com
질문 : CTR 계산식은 (클릭 횟수 / 노출 횟수) * 100 인데 문제에서 나온 계산식은
CTR (%) = 100.0 * 클릭 횟수 / 노출 횟수 로 계산하라고 나옴.
그리고 다음 수식으로 썼을 때, 답에 0으로 나옴.

SELECT
app_id,
SUM(CASE WHEN event_type = 'click' THEN 1 ELSE 0 END)
/ SUM(CASE WHEN event_type = 'impression' THEN 1 ELSE 0 END) AS ctr_rate
FROM events
GROUP BY app_id
;
이렇게 쓰면 3/4 = 0.75 가 ctr_rate로 나오길 바랬는데...왜...0...?

고민하다가 GPT에게 물어보니 납 득 완 료.
[GPT 답변]
아주 좋은 질문입니다!
당신이 제시한 두 식:
- ✅ 정답:
CTR (%) = 100.0 * Number of clicks / Number of impressions - ❌ 잘못된 식:
CTR (%) = 100 * (Number of clicks / Number of impressions)
🤔 그런데 왜 2번이 잘못됐다고 했을까?
사실 수학적으로는 두 식이 완전히 동일합니다.
그런데 이 질문의 핵심은 "SQL이나 프로그래밍 언어에서는 왜 (100.0 * 클릭수 / 노출수)를 쓰는가?" 또는 **"왜 100.0을 먼저 곱하나?"**에 대한 이야기로 해석됩니다.
💡 이유 1: 정수 나눗셈 문제
대부분의 SQL 엔진(예: PostgreSQL, SQL Server 등)에서는 아래처럼 동작합니다:
SELECT 1 / 4 → 0 -- 정수끼리 나눴으므로 결과는 0
SELECT 1.0 / 4 → 0.25 -- 실수 포함 → 실수 결과
따라서 100.0을 먼저 곱하면 나눗셈이 실수로 자동 전환되어 정확한 결과가 나옵니다:
100.0 * clicks / impressions → 올바른 실수 계산
반면에 이렇게 쓰면:
100 * clicks / impressions -- 정수 연산이면 중간 계산값 손실됨
정수끼리 먼저 나눠지면, 결과가 0이 되어버릴 수 있습니다.
💡 이유 2: 타입 강제 변환 (명시적 캐스팅 없이)
SELECT 100.0 * (clicks / impressions) -- 이 경우 clicks / impressions가 먼저 계산됨
위 식에서 clicks / impressions가 정수 나눗셈이면 0이 됨 →
결과: 100.0 * 0 = 0.0
🔍 그래서 어떻게 쓰는 게 좋을까?
💯 권장 패턴:
-- 가장 안전한 방식
100.0 * clicks / NULLIF(impressions, 0)
-- 또는
100.0 * (1.0 * clicks / NULLIF(impressions, 0))
-- 또는 명시적 캐스팅
100.0 * (CAST(clicks AS FLOAT) / NULLIF(impressions, 0))
이렇게 하면 0으로 나누는 오류도 방지하고, 실수형 연산도 보장됩니다.
✅ 결론
표현 결과 문제 가능성
| 100.0 * clicks / impressions | ✅ 정확 | 추천 |
| 100 * clicks / impressions | ❌ 정수 나눗셈 → 0 | 위험 |
| 100.0 * (clicks / impressions) | ⚠️ 안에 정수 나눗셈 → 0 | 위험 |
필요하시면 CTR 계산을 더 정밀하게 해주는 SQL 함수나, CTR이 낮은 앱 TOP 10을 추출하는 쿼리도 제공해드릴 수 있어요.
궁금하신가요? 😊
[정답 쿼리]
SELECT
app_id,
ROUND(100.0 *
SUM(CASE WHEN event_type = 'click' THEN 1 ELSE 0 END)
/ SUM(CASE WHEN event_type = 'impression' THEN 1 ELSE 0 END),2) AS ctr_rate
FROM events
WHERE timestamp >= '2022-01-01'
AND timestamp < '2023-01-01'
GROUP BY app_id
[오늘의 배움]
SQL에서는 정수끼리 나눗셈하면 0으로 결과가 나온다!!
실수로 출력하고 싶으면 실수를 곱하면 된다!!
'SQL' 카테고리의 다른 글
| [MySQL] COALESCE_가장 먼저 NULL이 아닌 값 반환 (0) | 2025.05.05 |
|---|---|
| [MySQL] 날짜 원하는 타입으로 출력 _ DATE_FORMAT (0) | 2025.04.29 |
| [PostgreSQL] ::, CASE_ type 변환 (0) | 2025.03.12 |
| [PostgreSQL] FILTER_SELECT문 속의 조건 (0) | 2025.03.12 |
| [SQL]LAG(), LEAD()함수 _현재 행의 이전 행의 값 참조하기 (0) | 2025.02.10 |