
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. 필터링 & 그룹화 전처리
- WHERE 절로 분석 대상 행을 먼저 제한
- 불필요한 NULL 값 처리 및 데이터 정규화
3.2. 그룹화 기준 선택
- 분석 목표에 맞는 컬럼(단일 또는 다중) 결정
- 범주형 컬럼(예: 지역, 제품 카테고리), 날짜 컬럼(예: 연도, 월) 활용
3.3. 집계 함수 적용
- COUNT: 행 수
- SUM/AVG: 수치 합계 및 평균
- MAX/MIN: 최댓값 및 최솟값
- GROUP_CONCAT (MySQL): 문자열 결합
3.4. 그룹 후 필터링 (HAVING)
- WHERE와 유사하나 그룹 단위로 조건 적용
- 예: 매출 합계 > 100,000
3.5. 결과 정렬 및 제한
- ORDER BY: 그룹화 결과 정렬
- 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 WHEN
과SUM
조합
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
의 필요성, 기본 문법, 단계별 사용법, 고급 기법, 최적화 방안, 실전 예제를 통합적으로 다루었다. 이를 통해 다양한 분석 시나리오에서 효율적이고 정확하게 데이터를 집계할 수 있다.