컴퓨터 과학/데이터 베이스

SQL에서 GROUP BY 사용 시 반드시 지켜야 할 규칙

Data Jun 2025. 8. 17. 22:07

SQL에서 데이터를 집계하거나 그룹별로 분석할 때 자주 사용하는 것이 바로 GROUP BY 구문입니다.

예를 들어, 아래와 같이 회원 데이터를 주요 지역과 성별별로 묶어서 살펴본다고 해보겠습니다.

SELECT 
    SUBSTRING(address, 1, 2) AS region,
    gender,
    COUNT(*) AS cnt
FROM copang_main.member
GROUP BY SUBSTRING(address, 1, 2), gender;

여기서는

  • 주요 지역(SUBSTRING(address, 1, 2) → region)
  • 성별(gender)

을 기준으로 서울-남성, 서울-여성, 경기-남성, 경기-여성 … 이런 식으로 그룹핑이 이루어집니다.

 

GROUP BY에서 반드시 지켜야 하는 규칙

GROUP BY를 사용할 때 SELECT 절에는 다음만 올 수 있습니다.

  1. GROUP BY 뒤에 사용한 컬럼들
  2. 집계 함수(aggregate function) → COUNT(), MAX(), AVG() 등

즉, 그룹핑 기준에 쓰이지 않은 컬럼을 SELECT 절에 그냥 가져다 쓰면 안 됩니다

 

규칙을 어겼을 때의 문제

예를 들어, age 컬럼을 SELECT 절에 그냥 추가해본다고 해보겠습니다.

SELECT 
    SUBSTRING(address, 1, 2) AS region,
    gender,
    age   -- 👈 GROUP BY에 포함되지 않은 컬럼
FROM copang_main.member
GROUP BY SUBSTRING(address, 1, 2), gender;

이 쿼리를 실행하면 MySQL에서는 다음과 같은 오류가 발생합니다.

Error Code: 1055.
Expression #3 of SELECT list is not in GROUP BY clause 
and contains nonaggregated column 'copang_main.member.age' 
which is not functionally dependent on columns in GROUP BY clause; 
this is incompatible with sql_mode=only_full_group_by

 

왜 이런 오류가 발생할까?

이유는 간단합니다.

GROUP BY를 통해 만들어진 각 row는 사실상 ‘하나의 그룹’을 대표합니다.
즉, 그 안에는 여러 개의 row(회원 데이터)가 묶여 있는 것이죠.

따라서 age 같은 컬럼을 SELECT 절에 그냥 넣어버리면,
"그룹 안에 여러 row들이 있는데 도대체 어떤 row의 age를 가져와야 하지?" 라는 문제가 생깁니다.

 

집계 함수와 함께라면 가능

하지만 AVG(age), MAX(age), MIN(age)처럼 집계 함수에 넣으면 문제가 해결됩니다.

예시:

SELECT 
    SUBSTRING(address, 1, 2) AS region,
    gender,
    AVG(age) AS avg_age
FROM copang_main.member
GROUP BY SUBSTRING(address, 1, 2), gender;

이 경우에는 특정 row의 age가 아니라,
그룹 전체의 평균 나이를 계산하면 되기 때문에 모호성이 사라집니다.

 

정리

  • GROUP BY 뒤에 쓴 컬럼은 SELECT 절에서도 그대로 사용할 수 있다.
  • GROUP BY 뒤에 쓰지 않은 컬럼은 SELECT 절에서 직접 쓸 수 없다.
  • 하지만 COUNT(), AVG(), MAX() 같은 집계 함수의 인자로는 사용할 수 있다.

👉 결국 GROUP BY를 쓰는 순간, SELECT 절의 결과 row는 **단일 데이터가 아니라 ‘하나의 그룹’**을 의미한다는 점을 꼭 기억해야 합니다.