6-2 연습 문제 — JOIN 뻥튀기 진단,
잘못된 SQL을 진단하고 고친다
섹션 6 연습의 정체성은 단 하나 — AI가 만든 잘못된 SQL을 진단하고 수정하는 것입니다. 눈으로 읽은 함정은 내일이면 잊히지만, 직접 진단하고 직접 고쳐본 SQL만 머리에 남습니다. 다 풀고 나면 본인 답을 AI 과외 선생님에게 던져 검증까지 받아보세요.
풀기 전에 — 진단 도구 점검
완료 ✓
완료 ✓
완료 ✓
지금 여기
다음 마일스톤
2-4에서 만든 AI 과외 선생님 세션을 그대로 쓰세요. 막히면 정답이 아니라 힌트만 요청하고 — “정답 말고 힌트만 줘” — 다 푼 뒤에는 본인 진단과 수정 SQL을 던지면서 “내 SQL 검증해줘” 라고 물어보세요. 본인 진단이 맞는지 AI에게 되묻는 메타 학습까지가 이번 연습입니다.
문제 1. SUM 뻥튀기 진단
다음 AI가 만든 SQL은 — “회원별 총 매출” 의도였습니다. 어떤 부풀림이 있는지 진단하고, 수정 SQL을 작성하세요.
-- ❌ AI 가 만든 (잘못된) SQL
SELECT
m.member_name,
SUM(p.price) AS 총매출 -- ⚠️ quantity 빠짐
FROM
members m
JOIN orders o
ON m.member_id = o.member_id
JOIN order_items oi
ON o.order_id = oi.order_id
JOIN products p
ON oi.product_id = p.product_id
GROUP BY
m.member_id,
m.member_name;컬럼 두 개 — price, quantity — 중 한 개를 누락하거나 곱하지 않으면 어떻게
될까?
정답 보기
진단: SUM(p.price)만 사용. quantity 곱하지 않음.
결과 — 김철수(member_id=1)의 주문 1에 프리미엄 그래놀라(12,000원) 수량 2인 행이 있습니다:
SUM(p.price)는 이 행에서 12,000원만 더함 — 진짜 매출은 12,000 × 2 = 24,000원.- 주문상세가 전부 수량 1인 회원은 두 값이 우연히 일치 — 한두 명만 보고 검증하면 속습니다.
- 일반적으로: quantity가 2 이상인 행이 있으면 매출이 적게 계산됨
| member_name | SUM(price) | SUM(price × quantity) |
|---|---|---|
| 김철수 | 486000 | 498000 ← 진짜 매출 |
수정 SQL:
SELECT
m.member_name,
SUM(p.price * oi.quantity) AS 총매출
FROM
members m
JOIN orders o
ON m.member_id = o.member_id
JOIN order_items oi
ON o.order_id = oi.order_id
JOIN products p
ON oi.product_id = p.product_id
GROUP BY
m.member_id,
m.member_name
ORDER BY
총매출 DESC;수량을 무시한 합계
그래놀라를 2개 사도 단가 12,000원이 한 번만 더해집니다. quantity가 2 이상인 행이 있는 회원은 매출이 적게 계산됩니다.
단가 × 수량의 합
한 주문상세 행의 매출 = 단가 × 수량. 행이 어떻게 펼쳐져 있든, 행마다 정확한 매출을 더합니다.
검산:
-- 김철수의 진짜 총 매출 — 단순 계산
SELECT
SUM(p.price * oi.quantity)
FROM
orders o
JOIN order_items oi
ON o.order_id = oi.order_id
JOIN products p
ON oi.product_id = p.product_id
WHERE
o.member_id = 1;
-- → 498000이 값이 위 수정 SQL의 김철수 행과 일치해야 정상.
문제 2. 평균 객단가 진단 (가장 위험한 패턴)
다음 SQL은 “회원별 평균 객단가” 의도. 어디가 잘못됐는지 진단하고, CTE로 수정하세요.
-- ❌ AI 가 만든 (잘못된) SQL
SELECT
m.member_name,
AVG(p.price * oi.quantity) AS 평균_객단가
FROM
members m
JOIN orders o
ON m.member_id = o.member_id
JOIN order_items oi
ON o.order_id = oi.order_id
JOIN products p
ON oi.product_id = p.product_id
GROUP BY
m.member_id,
m.member_name;한 주문에 상품 3 개 있으면 — AVG가 3 개의 행별 매출 평균을 냄. 그게
“주문당 평균” 이 맞나?
정답 보기
진단: AVG(price × quantity)는 — 주문상세 행별 매출의 평균. 객단가 (= 한 주문당 평균)가 아님.
구체적 예: 김철수의 주문 14는 책 3 권 — SQL 입문서 24,000 + 데이터 모델링 실전 32,000 + AI 시대 개발자 28,000:
- 진짜 주문 총액 = 84,000 원
- AI의 평균 =
(24000 + 32000 + 28000) / 3= 28,000 원
→ 3 배 작게 나옴.
| member_name | 잘못된 SQL | 수정 SQL (CTE) |
|---|---|---|
| 김철수 | 49800 | 83000 ← 진짜 객단가 |
수정 SQL (CTE):
WITH order_totals AS (
SELECT
o.order_id,
o.member_id,
SUM(p.price * oi.quantity) AS order_total
FROM
orders o
JOIN order_items oi
ON o.order_id = oi.order_id
JOIN products p
ON oi.product_id = p.product_id
GROUP BY
o.order_id,
o.member_id
)
SELECT
m.member_name,
AVG(ot.order_total) AS 평균_객단가
FROM
members m
JOIN order_totals ot
ON m.member_id = ot.member_id
GROUP BY
m.member_id,
m.member_name
ORDER BY
평균_객단가 DESC;단계:
- 주문별 총액 (CTE
order_totals) — order_items 행 N 개를 1 행으로 합침. - 그 다음 회원별 — 주문 총액들의 평균.
펼쳐진 행에 AVG를 바로
한 주문이 상품 수만큼 행으로 펼쳐진 상태에서 AVG — 주문상세 행별 매출의 평균이 나옵니다. 김철수는 49,800원 — 진짜 객단가의 60% 수준.
CTE로 주문 총액부터
먼저 주문별 총액으로 합치고(행 N 개 → 1 행), 그 총액들의 평균 — 김철수 83,000원. 객단가의 정의 그대로입니다.
검산: 김철수 주문 6 건의 진짜 객단가 평균을 손으로 계산해서 (또는 단순 SQL로) 비교 → 498,000 ÷ 6 = 83,000 원.
문제 3 (도전). AI와 검산 협업 — 실시연
6-2 본문의 모범 SQL (회원별 총 매출)을 실제로 AI에게 던지고 — 그 결과를 검산하는 후속 메시지까지 진행하세요.
shop 정리본(테이블 + 관계)과 요구사항을 함께 보냅니다. 회원별 총 매출 — price × quantity 합, 매출 많은 순.
그럴듯한 결과가 나옵니다. 여기서 끝내면 6-1 이전의 나 — 검산 전까지는 가설일 뿐입니다.
행 수 검산 SQL과 단순 집계 SQL — 검산 SQL까지 AI에게 시키는 것이 이 문제의 핵심입니다.
AI가 만든 검산 SQL들도 DBeaver에서 실행하고, 메인 쿼리의 값과 일치하는지 비교합니다.
보낼 메시지 ① — SQL 요청:
[테이블 + 관계] (shop 정리본)
[요구사항]
회원별 총 매출 (price × quantity 합). 매출 많은 순.보낼 메시지 ② — 검산 요청:
방금 SQL 의 결과를 검산하고 싶어:
1. 이 JOIN 결과의 총 행 수가 — order_items (64 행) 과 같은지 확인하는 SQL.
2. 김철수 (member_id=1) 의 *진짜 매출* 을 — 단순 한 줄 SQL 로 구해줘.
이 두 결과를 메인 쿼리와 비교해서 부풀림이 없는지 점검할 거야.가이드
기대되는 AI 응답:
-- 1. JOIN 결과 행 수
SELECT
COUNT(*)
FROM
members m
JOIN orders o
ON m.member_id = o.member_id
JOIN order_items oi
ON o.order_id = oi.order_id
JOIN products p
ON oi.product_id = p.product_id;
-- → 64 ✓
-- 2. 김철수 매출
SELECT
SUM(p.price * oi.quantity) AS 김철수_매출
FROM
orders o
JOIN order_items oi
ON o.order_id = oi.order_id
JOIN products p
ON oi.product_id = p.product_id
WHERE
o.member_id = 1;
-- → 498000| COUNT(*) |
|---|
| 64 ← order_items 행 수와 동일 |
| 김철수_매출 |
|---|
| 498000 ← 메인 SQL 의 김철수 행과 일치 |
검산 결과 일치 확인:
- 메인 SQL의 김철수 행 매출 == 단순 SQL 결과 → ✓ 정상
- 일치 안 하면 → 메인 SQL의 JOIN 또는 집계에 뻥튀기.
AI한테 “검산도 시킨다” — 본인이 짜는 시간보다 훨씬 빠르고 정확. AI 협업 검증의 진수.
세 문제 모두 진단 → 수정 → 검산까지 직접 해봤다면, AI가 만든 SQL 앞에서 가장 비싼 사고를 미리 겪고 백신까지 맞은 셈입니다. 다음 단골 함정은 — 0도 아니고 빈 문자열도 아닌, NULL입니다.