SQL GROUP BY 핸드북

핵심 요약: GROUP BY 절은 테이블 내의 행들을 지정한 컬럼 값별로 그룹화하여 집계 함수를 적용할 수 있게 해준다. 데이터 요약, 보고서 생성, 인사이트 도출에 필수적인 기능이다.


1. 도입 및 필요성

데이터베이스에서 대량의 행을 단순히 조회하는 것만으로는 유의미한 패턴이나 통계치를 얻기 어려우므로, 공통 값을 기준으로 데이터를 집계하여 분석할 필요가 있다.

  • 집계 함수 활용: SUM, COUNT, AVG, MAX, MIN 등을 그룹 단위로 적용
  • 보고서 생성: 분기별 매출, 지역별 주문 수, 사용자 활동 통계 등
  • 데이터 무결성 확인: 특정 조건 하에서 누락되거나 오류가 있는 그룹 식별

2. 기본 구조

SELECT
  그룹화_컬럼1,
  그룹화_컬럼2,
  집계함수1(대상_컬럼) AS 별칭1,
  집계함수2(대상_컬럼) AS 별칭2
FROM
  테이블명
WHERE
  필터링_조건
GROUP BY
  그룹화_컬럼1,
  그룹화_컬럼2
HAVING
  그룹_조건
ORDER BY
  정렬_컬럼 [ASC|DESC];
  • SELECT: 반환할 컬럼과 집계 결과 지정
  • WHERE: 그룹화 전 필터링
  • GROUP BY: 집계할 기준 컬럼 나열
  • HAVING: 그룹화 후 조건 필터링
  • ORDER BY: 결과 정렬

3. 사용법 단계별 가이드

3.1. 필터링 & 그룹화 전처리

  1. WHERE 절로 분석 대상 행을 먼저 제한
  2. 불필요한 NULL 값 처리 및 데이터 정규화

3.2. 그룹화 기준 선택

  1. 분석 목표에 맞는 컬럼(단일 또는 다중) 결정
  2. 범주형 컬럼(예: 지역, 제품 카테고리), 날짜 컬럼(예: 연도, 월) 활용

3.3. 집계 함수 적용

  1. COUNT: 행 수
  2. SUM/AVG: 수치 합계 및 평균
  3. MAX/MIN: 최댓값 및 최솟값
  4. GROUP_CONCAT (MySQL): 문자열 결합

3.4. 그룹 후 필터링 (HAVING)

  1. WHERE와 유사하나 그룹 단위로 조건 적용
  2. 예: 매출 합계 > 100,000

3.5. 결과 정렬 및 제한

  1. ORDER BY: 그룹화 결과 정렬
  2. LIMIT: 최상위 그룹만 출력

4. 고급 활용 기법

4.1. 다중 집계 및 다중 그룹화

SELECT region, product_category,
       COUNT(*) AS order_count,
       SUM(amount) AS total_sales,
       AVG(discount) AS avg_discount
FROM orders
GROUP BY region, product_category;

4.2. 윈도우 함수와 결합

  • OVER (PARTITION BY ...)로 비슷한 결과를 얻지만, 원본 행 유지 가능
SELECT  
  user_id,
  order_date,
  SUM(amount) OVER (PARTITION BY user_id ORDER BY order_date) AS cumulative_spend
FROM orders;

4.3. 서브쿼리 활용

  • 복잡한 필터링을 위해 그룹화 결과를 서브쿼리로 사용
SELECT t.region, t.total_sales
FROM (
  SELECT region, SUM(amount) AS total_sales
  FROM orders
  GROUP BY region
) AS t
WHERE t.total_sales > 100000;

4.4. 동적 그룹화 (피벗)

  • CASE WHENSUM 조합
SELECT
  month,
  SUM(CASE WHEN region = 'East' THEN amount ELSE 0 END) AS east_sales,
  SUM(CASE WHEN region = 'West' THEN amount ELSE 0 END) AS west_sales
FROM orders
GROUP BY month;

5. 주의사항 및 최적화

  • NULL 처리: 그룹화 컬럼에 NULL이 있으면 하나의 그룹으로 묶임
  • 인덱스 활용: 그룹화 컬럼에 인덱스 생성 시 성능 개선
  • 메모리 사용: 대규모 데이터셋은 메모리 및 임시 테이블 생성 주의
  • 정규화 vs. 비정규화: 조인 후 그룹화 시 데이터 양 폭증 주의

6. 실전 예제

-- 1) 분기별 매출 합계
SELECT
  CONCAT(YEAR(order_date), '-Q', QUARTER(order_date)) AS quarter,
  SUM(amount) AS quarter_sales
FROM orders
WHERE order_date BETWEEN '2025-01-01' AND '2025-12-31'
GROUP BY YEAR(order_date), QUARTER(order_date)
HAVING SUM(amount) > 500000
ORDER BY quarter;
 
-- 2) 사용자별 평균 주문 금액
SELECT
  user_id,
  AVG(amount) AS avg_order_amount
FROM orders
GROUP BY user_id
ORDER BY avg_order_amount DESC
LIMIT 10;

핸드북 정리: 이 핸드북에서는 GROUP BY의 필요성, 기본 문법, 단계별 사용법, 고급 기법, 최적화 방안, 실전 예제를 통합적으로 다루었다. 이를 통해 다양한 분석 시나리오에서 효율적이고 정확하게 데이터를 집계할 수 있다.