AI 시대 DB 모델링 & SQL 완벽 마스터6-4 연습 문제
테크타니 LEARN — 섹션 06 · 연습 문제

6-4 연습 문제 — GROUP BY 진단,
직접 고쳐본 SQL만 머리에 남는다

섹션 6 연습의 정체성 — AI가 만든 잘못된 SQL을 진단하고 직접 수정하기. 이번엔 GROUP BY입니다. 누락 컬럼 · 집계 단위 · 비중 분모 세 함정 — 에러 없이 임의 값이 나오는 곳, 일별이 분기별로 둔갑한 곳, 모든 비중이 100%로 찍히는 곳을 직접 잡아냅니다.

문제3문제 (도전 1 포함)권장 소요15~20분사용 테이블members · categories · products · orders · order_items준비물DBeaver + AI 과외 선생님 (2-4)

이번 연습의 위치

6-1 ~ 6-3

완료 ✓

6-4 GROUP BY 단위 오류

강의 완료 ✓

6-4 연습 문제

지금 여기

6-5 검증 체크리스트 ★

섹션 6 마무리

AI 과외 선생님 활용법

2-4에서 만든 AI 과외 선생님 세션을 그대로 쓰세요. 먼저 혼자 진단해 보고 — 막히면 정답이 아니라 힌트만 요청하세요. 다 푼 뒤에는 본인의 진단과 수정 SQL을 던지며 “내 SQL 검증해줘” 라고 요청하면, GROUP BY에 빠진 컬럼이 없는지·집계 단위가 의도와 맞는지까지 짚어줍니다.

문제 1. GROUP BY 누락 컬럼 진단

다음 SQL — 무엇이 문제? MySQL에서 실행하면 어떤 결과가 나올까?

-- ❌ AI 가 만든 SQL
SELECT
  m.member_name,
  m.gender,
  m.age,
  COUNT(o.order_id) AS 주문수
FROM
  members m
LEFT JOIN orders o
  ON m.member_id = o.member_id
GROUP BY
  m.member_id;
정답 보기

문제: SELECT에 member_name, gender, age가 있는데 GROUP BY에는 member_id만.

✕ MySQL (기본 모드)

에러 없이 조용히 통과합니다

member_id 그룹에서 — member_name, gender, age임의 한 값을 반환. shop 데이터에선 한 member_id에 한 회원이라 결과가 정확해 보일 수 있음. 하지만 DB가 보장하는 게 아님.

✓ 다른 DB (PostgreSQL, Oracle 등)

에러가 납니다 — 차라리 안전

비집계 컬럼이 GROUP BY에 없으면 즉시 에러 발생. 잘못된 SQL이 보고서까지 흘러가기 전에 막아줍니다.

수정:

SELECT
  m.member_name,
  m.gender,
  m.age,
  COUNT(o.order_id) AS 주문수
FROM
  members m
LEFT JOIN orders o
  ON m.member_id = o.member_id
GROUP BY
  m.member_id,
  m.member_name,
  m.gender,
  m.age;
✓ 규칙

비집계 컬럼 모두 GROUP BY에 추가.

member_id가 PK라서 다른 컬럼들이 함수 종속이지만 — 명시가 안전.

문제 2. 집계 단위 오류

다음 SQL — “분기별 매출” (Q1, Q2, Q3, Q4) 의도. 잘못됐나? 어떻게 수정?

-- ❌
SELECT
  ordered_at,
  SUM(p.price * oi.quantity) AS 매출
FROM
  orders o
JOIN order_items oi USING(order_id)
JOIN products p USING(product_id)
GROUP BY
  ordered_at;
정답 보기

진단: GROUP BY ordered_at일별로 묶음. 분기별 아님.

수정 (MySQL):

SELECT
  CONCAT(YEAR(ordered_at), '-Q', QUARTER(ordered_at)) AS 분기,
  SUM(p.price * oi.quantity) AS 매출
FROM
  orders o
JOIN order_items oi USING(order_id)
JOIN products p USING(product_id)
GROUP BY
  분기
ORDER BY
  분기;

핵심 함수:

  • YEAR(date) — 연도 추출
  • QUARTER(date) — 분기 (1~4) 추출
  • CONCAT(...) — 문자열 결합
DBeaver — 분기별 매출 (결과 예)
SELECT CONCAT(YEAR(ordered_at), '-Q', QUARTER(ordered_at)) AS 분기, ... GROUP BY 분기;
분기매출
2025-Q1280000
2025-Q2410000
2025-Q3350000
2025-Q4520000
2026-Q1380000
일별 수십 행 → 분기별 5행 — 의도한 집계 단위

문제 3 (도전). 비중 계산 + 다중 함정

다음 SQL — “카테고리별 매출 + 그 카테고리가 전체에서 차지하는 비중 (%)” 의도. 두 개 함정이 있어요.

-- ❌ AI 가 만든 (잘못된) SQL
SELECT
  category_id,
  category_name,
  SUM(price * quantity) AS 매출,
  SUM(price * quantity) / SUM(price * quantity) * 100 AS 비중_퍼센트
FROM
  categories c
JOIN products p
  ON c.category_id = p.category_id
JOIN order_items oi
  ON p.product_id = oi.product_id
GROUP BY
  category_id;

1. 두 가지 함정을 찾으세요. 2. 수정 SQL을 작성하세요.

정답 보기
✕ 함정 1 — GROUP BY 누락

category_name이 빠졌습니다

SELECT에 category_name 있는데 GROUP BY에는 category_id만. MySQL은 허용 (category_id가 PK라 함수 종속) — 하지만 명시가 안전.

✕ 함정 2 — 비중 분모 오류

항상 100%가 나옵니다

SUM(price * quantity) / SUM(price * quantity) * 100 — 분모도 “이 그룹 안 SUM”. 항상 100%가 나옴. 모든 카테고리 비중 = 100%.

수정:

SELECT
  c.category_id,
  c.category_name,
  SUM(p.price * oi.quantity) AS 매출,
  SUM(p.price * oi.quantity)
    / (SELECT
         SUM(p2.price * oi2.quantity)
       FROM
         products p2
       JOIN order_items oi2 USING(product_id))
    * 100 AS 비중_퍼센트
FROM
  categories c
JOIN products p
  ON c.category_id = p.category_id
JOIN order_items oi
  ON p.product_id = oi.product_id
GROUP BY
  c.category_id,
  c.category_name
ORDER BY
  매출 DESC;

수정 두 곳:

  1. GROUP BY c.category_id, c.category_name — category_name 추가
  2. 분모를 서브쿼리로 — 그룹 밖의 전체 합
DBeaver — 카테고리별 매출 + 비중 (기대 결과 예시)
SELECT c.category_name, SUM(...) AS 매출, ... * 100 AS 비중_퍼센트 ... ORDER BY 매출 DESC;
category_name매출비중_퍼센트
의류80000030
전자기기70000026.5
도서50000019
뷰티35000013
식품30000011.5
비중 합 = 100% ✓ — 검산

더 우아한 대안 — 윈도우 함수:

SELECT
  c.category_name,
  SUM(p.price * oi.quantity) AS 매출,
  SUM(p.price * oi.quantity) * 100.0
    / SUM(SUM(p.price * oi.quantity)) OVER () AS 비중_퍼센트
FROM
  categories c
JOIN products p
  ON c.category_id = p.category_id
JOIN order_items oi
  ON p.product_id = oi.product_id
GROUP BY
  c.category_id,
  c.category_name;

SUM(SUM(...)) OVER ()“GROUP BY 결과의 모든 SUM의 합” (= 전체 합)을 윈도우 함수로.

비집계 컬럼은 GROUP BY에 명시, 집계 단위는 날짜 함수로 의도에 맞게, 비중 분모는 그룹 밖 전체 합으로 — 세 함정을 직접 고쳐봤다면, 이제 섹션 6의 화룡점정인 검증 체크리스트로 모든 무기를 하나의 습관으로 묶을 차례입니다.

NEXT LESSON6-5 검증 체크리스트 + 디버깅 ★

JOIN 뻥튀기·NULL·GROUP BY — 지금까지 배운 함정 전부를 실행 전 체크리스트 하나로 묶어, AI SQL을 검증하는 루틴을 완성합니다.

GO ▸ 다음 강의 시작하기