6-5 연습 문제 — 종합 진단 ★,
5 패턴이 한 SQL에 다 섞여 나옵니다
섹션 6의 마지막 연습 — 종합전입니다. 이번 문제의 SQL들은 패턴이 하나씩 얌전히 나오지 않아요. 여러 함정이 한 SQL에 동시에 들어가 있습니다. 6-5 체크리스트 5 항목을 빠짐없이 적용해서 진단하세요 — 직접 진단하고 고쳐본 SQL만 머리에 남습니다.
이번 연습의 위치
완료 ✓
완료 ✓
강의 완료 ✓
지금 여기
더 깊이 + 실무 주의사항
진단 도구 — 체크리스트 5 항목 리마인드
문제를 풀기 전에, 6-5 강의에서 만든 검증 체크리스트를 머릿속에 다시 올려두세요. 아래 5 항목을 순서대로 돌리는 게 이번 연습의 룰입니다.
2-4에서 만든 AI 과외 선생님 세션을 그대로 쓰세요. 먼저 혼자 체크리스트를 돌리고 — 막히면 정답이 아니라 힌트만 요청하세요. 다 푼 뒤에는 본인의 진단·수정 SQL을 던지며 “내 SQL 검증해줘” 라고 요청하면, 검증 사이클을 한 번 더 연습하는 효과까지 있습니다.
문제 1. 4 패턴 동시 등장
다음 AI가 만든 SQL — 무려 4 가지 패턴이 다 들어가 있습니다. 요구사항: “활성 회원의 카테고리별 평균 객단가” (회사 정의: 활성 = 지난 1년 안에 주문).
-- ❌ AI 가 만든 SQL (다중 함정)
SELECT
m.member_name,
c.category_name,
AVG(p.price * oi.quantity) AS 평균_객단가
FROM
members m
LEFT JOIN orders o
ON m.member_id = o.member_id
LEFT JOIN order_items oi
ON o.order_id = oi.order_id
LEFT JOIN products p
ON oi.product_id = p.product_id
LEFT JOIN categories c
ON p.category_id = c.category_id
WHERE
m.is_active = 1
GROUP BY
m.member_id,
c.category_id;4 가지 함정 찾으세요:
정답 보기
함정 1 — 패턴 4 (환각)
m.is_active — shop의 members에 is_active 컬럼 없음. AI가 “활성 회원” 이라는 단어 보고 있을 거 같은 컬럼 만들어 씀.
함정 2 — 패턴 5 (의미 오류)
“활성” 의 정의가 “지난 1년 안에 주문” 인데 — SQL은 is_active = 1로 추측. 의도와 다름.
함정 3 — 패턴 1 (JOIN 뻥튀기)
AVG(price × quantity) — 객단가 (주문별 평균)가 아니라 행별 평균. 6-2의 사례 2.
함정 4 — 패턴 3 (GROUP BY 누락)
SELECT에 member_name, category_name — GROUP BY에는 member_id, category_id. 두 _name 컬럼이 누락 (MySQL 허용하나 다른 DB 에러).
추가 함정 — 패턴 2 (NULL)
LEFT JOIN 4 개 — 객단가가 NULL인 회원이 있을 수 있음 (활성이지만 주문 없는 경우 추정). COALESCE 없음.
문제 2. 위 SQL을 완벽히 수정
문제 1의 SQL을 — 4 가지 함정 모두 해결 하여 다시 작성하세요.
모범 답안
-- ✅ 수정 (다중 함정 모두 해결)
WITH active_members AS (
-- 패턴 5 해결: "활성" 을 회사 정의로 명시
SELECT DISTINCT
m.member_id,
m.member_name
FROM
members m
JOIN orders o
ON m.member_id = o.member_id
WHERE
o.ordered_at >= CURDATE() - INTERVAL 1 YEAR
),
order_totals AS (
-- 패턴 1 해결: 객단가 = 주문별 총액의 평균. CTE 단계 분리
SELECT
o.order_id,
o.member_id,
p.category_id,
SUM(p.price * oi.quantity) AS order_total
FROM
orders o
JOIN order_items oi USING(order_id)
JOIN products p USING(product_id)
WHERE
o.ordered_at >= CURDATE() - INTERVAL 1 YEAR
GROUP BY
o.order_id,
o.member_id,
p.category_id
)
SELECT
am.member_name,
c.category_name,
COALESCE(AVG(ot.order_total), 0) AS 평균_객단가 -- 패턴 2 해결: NULL → 0
FROM
active_members am
JOIN order_totals ot
ON am.member_id = ot.member_id
JOIN categories c
ON ot.category_id = c.category_id
GROUP BY
am.member_id,
am.member_name,
c.category_id,
c.category_name -- 패턴 3 해결: 모든 비집계 컬럼
ORDER BY
am.member_name,
평균_객단가 DESC;해결 매핑:
| 함정 | 해결 |
|---|---|
환각 (is_active) | 실제 스키마만 사용 — orders.ordered_at 기준 |
| 의미 오류 (“활성”) | CURDATE() - INTERVAL 1 YEAR로 회사 정의 명시 |
| JOIN 뻥튀기 (AVG) | CTE (order_totals)로 주문별 총액 → 그 위에 AVG |
| GROUP BY 누락 | 모든 비집계 컬럼 (4 개) GROUP BY에 |
| NULL | COALESCE(AVG(...), 0) |
검산 권장:
- 한 회원 한 카테고리 골라 — 그 회원이 그 카테고리에서 한 주문들의 총액 평균을 단순 SQL로 계산
- 이 결과와 메인 SQL의 해당 행 비교
문제 3 (도전). 본인이 AI가 되어 검증
다음은 마케팅팀에서 받은 가상 요청:
“이번 분기 (Q1 2026)에 — 30대 여성 회원의 카테고리별 매출 비중 (%)을 알려주세요. 신규 회원도 포함해서.”
1. 이 요청을 받은 AI가 만들었을 만한 SQL 한 개를 직접 작성 해보세요. 2. 본인이 만든 SQL에 — 5 패턴 체크리스트를 적용해서 자가 진단. 3. 발견된 함정을 모두 수정 한 최종 SQL.
이 문제의 핵심: “AI 입장에서 생각해보면서 — 함정에 미리 빠져보고, 본인이 잡는 연습.”
가이드
Step 1. AI가 만들 만한 SQL (다중 함정 포함)
-- 1차 시도 (함정 포함)
SELECT
c.category_name,
SUM(p.price * oi.quantity) AS 매출,
SUM(p.price * oi.quantity) / SUM(p.price * oi.quantity) * 100 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
JOIN categories c
ON p.category_id = c.category_id
WHERE
m.gender = 'F'
AND m.age >= 30 -- "30대" 모호
AND o.ordered_at LIKE '2026-01%' -- Q1 의도 - 1월만 잡힘
GROUP BY
c.category_id; -- category_name 누락Step 2. 자가 진단
| 체크 | 결과 |
|---|---|
| JOIN 뻥튀기 | ⚠️ SUM 자체는 정확 (price × quantity), 행 수 검산 필요 |
| NULL | OK (INNER JOIN이라 NULL 없음) |
| GROUP BY | ⚠️ category_name 누락 |
| 환각 | OK (모든 컬럼 실제 존재) |
| 의미 | ❌ “30대” → age >= 30 (40대도 포함). Q1 → 1월만. “신규” 정의 없음. |
Step 3. 수정 SQL
-- ✅ 최종 수정
SELECT
c.category_id,
c.category_name,
SUM(p.price * oi.quantity) AS 매출,
SUM(p.price * oi.quantity) * 100.0
/ (
SELECT
SUM(p2.price * oi2.quantity)
FROM
members m2
JOIN orders o2
ON m2.member_id = o2.member_id
JOIN order_items oi2
ON o2.order_id = oi2.order_id
JOIN products p2
ON oi2.product_id = p2.product_id
WHERE
m2.gender = 'F'
AND m2.age BETWEEN 30 AND 39
AND o2.ordered_at BETWEEN '2026-01-01' AND '2026-03-31'
) 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
JOIN categories c
ON p.category_id = c.category_id
WHERE
m.gender = 'F'
AND m.age BETWEEN 30 AND 39 -- 30대 정확화
AND o.ordered_at BETWEEN '2026-01-01' AND '2026-03-31' -- Q1 정확화
GROUP BY
c.category_id,
c.category_name -- 모든 비집계 컬럼
ORDER BY
매출 DESC;참고: “신규 회원도 포함” 은 — 30대 여성 조건과 OR 결합 또는 “신규 정의 확인 필요” 로 마케팅팀에 되묻기. “AI가 모르는 비즈니스 영역” 의 대표 사례.
이 문제의 메시지: “AI가 SQL 짜기 전에 — 사람이 ‘의미’를 먼저 정확히 정의해야 한다.” 함정 1~3 (SQL 적)은 AI가 도와줄 수 있지만 — 함정 5 (비즈니스 의미)는 무조건 사람이.
섹션 6 완료 — 강의 전체 핵심 완성
여기까지 푸셨다면 — 이 한 줄을 손에 잡은 상태입니다.
| 기둥 | 어디서 | 손에 잡힌 능력 |
|---|---|---|
| 모델링 | 섹션 4 | 부모-자식 사고법 |
| AI 협업 | 섹션 5 | 3가지 컨텍스트 + 단계 분해 |
| 검증 | 섹션 6 | 5 패턴 진단 + 검증 체크리스트 |
강의의 세 기둥이 모두 세워졌습니다. 이제 마지막 섹션 — 여기서 더 깊이 가는 길과, 실무에서 꼭 지켜야 할 주의사항만 남았습니다.