GROUP BY와 집계 함수 소개

Ryan·2025년 1월 14일

SQL/Python 분석

목록 보기
48/94

데이터베이스를 다루다 보면, 단순히 행(Row)을 조회하는 것만으로는 충분하지 않을 때가 많습니다. 예를 들어, 부서별 평균 급여를 구하거나, 제품별 판매량 합계를 알고 싶다면, GROUP BY 구문과 집계 함수를 활용해야 합니다. 이번 글에서는 SQL에서 자주 쓰이는 GROUP BY 구문과 대표적인 집계 함수(aggregate functions)를 알아보겠습니다.


1. GROUP BY란?

  • GROUP BY 구문은 특정 컬럼을 기준으로 레코드(행)을 그룹화하는 역할을 합니다.
  • 그룹화된 각 그룹별로 집계 함수(SUM, COUNT, AVG, MIN, MAX 등)를 적용해 통계량을 얻을 수 있습니다.

기본 문법

sql
코드 복사
SELECT 컬럼1, 집계함수(컬럼2)
FROM 테이블명
[WHERE 조건]
GROUP BY 컬럼1;
  • 컬럼1: 그룹화의 기준이 되는 컬럼
  • 집계함수(컬럼2): 집계 연산을 적용할 대상 컬럼 (예: 월급, 매출액, 인원 수 등)

2. 대표적인 집계 함수(aggregate functions)

2.1 COUNT()

  • 행(Row)의 개수를 세어줍니다.
  • 예: COUNT(*)는 해당 그룹(또는 전체 테이블)의 행 개수, COUNT(컬럼명)은 해당 컬럼에 NULL이 아닌 값의 개수를 센다는 차이가 있습니다.

예시

sql
코드 복사
SELECT Department, COUNT(*) AS dept_count
FROM employee
GROUP BY Department;
  • employee 테이블에서 부서(Department)를 기준으로 직원 수(dept_count)를 구함

2.2 SUM()

  • 합계를 구할 때 사용
  • 수치형(정수, 실수) 컬럼에만 적용 가능합니다.

예시

sql
코드 복사
SELECT Department, SUM(MonthlyIncome) AS total_income
FROM employee
GROUP BY Department;
  • 부서별 월급의 총합을 구함

2.3 AVG()

  • 평균을 구할 때 사용
  • 역시 수치형 컬럼에만 적용 가능하며, SUM(컬럼)/COUNT(컬럼)과 동일한 개념

예시

sql
코드 복사
SELECT Department, AVG(MonthlyIncome) AS avg_income
FROM employee
GROUP BY Department;
  • 부서별로 평균 월급을 구해줌

2.4 MIN(), MAX()

  • 최솟값최댓값을 구하는 함수
  • 날짜/시간 타입에도 적용 가능 (가장 빠른 날짜, 가장 최근 날짜 등)

예시

sql
코드 복사
SELECT
    Department,
    MIN(Age) AS min_age,
    MAX(Age) AS max_age
FROM employee
GROUP BY Department;
  • 부서별로 최소 나이(min_age)최대 나이(max_age)를 함께 조회

3. GROUP BY와 다른 구문 결합

3.1 WHERE와 함께 사용

  • WHERE 절은 GROUP BY로 그룹화하기 이전에 조건을 적용
  • 예: 특정 기간이나 특정 지역만 조회 후, 그룹화 진행
sql
코드 복사
SELECT Department, AVG(MonthlyIncome) AS avg_income
FROM employee
WHERE Age > 30
GROUP BY Department;
  • 30세 초과 직원들만 대상으로, 부서별 평균 월급을 구함

3.2 HAVING 절

  • 그룹화된 결과에 추가 조건을 적용하려면 HAVING 절을 사용
  • WHERE는 그룹화 전에 조건을, HAVING그룹화 후 조건을 적용
sql
코드 복사
SELECT Department, AVG(MonthlyIncome) AS avg_income
FROM employee
GROUP BY Department
HAVING AVG(MonthlyIncome) > 6000;
  • 부서별 평균 월급이 6000 초과인 부서만 조회

3.3 ORDER BY와 함께 사용

  • 보통 GROUP BY로 집계 결과를 구한 뒤, 정렬하고 싶을 때 ORDER BY를 추가
  • 예: 합계, 평균 등 집계 결과에 따라 오름/내림차순 정렬
sql
코드 복사
SELECT Department, COUNT(*) AS dept_count
FROM employee
GROUP BY Department
ORDER BY dept_count DESC;
  • 직원 수(dept_count)가 많은 부서부터 차례대로 내림차순으로 정렬

4. 실무 예시

4.1 제품 판매 테이블 예시

order_idproduct_idquantitypricesale_date
1P001210002023-01-01
2P002320002023-01-02
3P001110002023-01-02
4P003430002023-01-03
...............

4.1.1 제품별 총 판매 수량

sql
코드 복사
SELECT product_id, SUM(quantity) AS total_sold
FROM sales
GROUP BY product_id;
  • 각 제품(product_id)별로 판매 수량(quantity)의 합을 보여줌

4.1.2 하루 매출 합계

sql
코드 복사
SELECT sale_date, SUM(quantity * price) AS daily_revenue
FROM sales
GROUP BY sale_date;
  • 날짜별로 (수량 × 단가)의 합을 구해 일별 매출 확인

4.1.3 특정 날짜 범위 + 매출 상위 일자

sql
코드 복사
SELECT sale_date, SUM(quantity * price) AS daily_revenue
FROM sales
WHERE sale_date BETWEEN '2023-01-01' AND '2023-01-31'
GROUP BY sale_date
HAVING SUM(quantity * price) > 10000
ORDER BY daily_revenue DESC;
  • 1월 한 달 동안 날짜별 매출이 10,000 초과인 날짜만 뽑아서, 매출이 높은 순으로 정렬

5. 주의사항 & 팁

  1. SELECT 목록과 GROUP BY 컬럼
    • 대부분의 DB에서, GROUP BY에서 묶이지 않은 컬럼은 집계 함수로 감싸지 않으면 에러가 남
    • MySQL에서는 ONLY_FULL_GROUP_BY 모드가 꺼져 있으면 예외적으로 허용될 수도 있지만, 표준 SQL을 준수하는 것이 좋음
  2. 집계 결과 컬럼에 별칭 부여
    • AS 키워드를 사용하면 코드 가독성과 결과 확인이 편해짐 (예: AS total_income)
  3. NULL 값 처리
    • COUNT(컬럼명)은 해당 컬럼이 NULL인 행을 제외
    • COUNT(*)는 모든 행을 카운트
    • SUM, AVG 등의 연산도 NULL 값을 무시하지만, NULL만 있는 경우 결과가 NULL이 될 수 있음
  4. 성능 주의
    • 데이터가 매우 많을 경우, GROUP BY 시 인덱스를 어떻게 설정하느냐가 성능에 영향을 줌
    • 필요 시 EXPLAIN 등으로 쿼리 실행 계획을 확인

마무리

GROUP BY집계 함수를 적절히 사용하면, 분석용 통계부터 일일·월별 보고서까지 다양한 정보를 뽑아낼 수 있습니다.

여기에 HAVING, ORDER BY, WHERE를 결합하여 조건 필터링과 정렬을 더하면, 좀 더 정교한 집계 결과를 얻을 수 있습니다.

0개의 댓글