- [MySQL] ONLY_FULL_GROUP_BY 오류: 개념과 해결 방법2025년 06월 18일 09시 48분 12초에 업로드 된 글입니다.작성자: DandyNow728x90반응형
MySQL ONLY_FULL_GROUP_BY 오류: 개념과 해결 방법
MySQL을 사용하면서
GROUP BY쿼리 작성 시In aggregated query without GROUP BY, expression #N of SELECT list contains nonaggregated column ... this is incompatible with sql_mode=only_full_group_by와 같은 오류 메시지를 만나는 경우가 많다. 이 오류는ONLY_FULL_GROUP_BY라는 MySQL SQL 모드 때문에 발생한다. 이 블로그 포스팅에서는ONLY_FULL_GROUP_BY가 무엇인지, 왜 이런 오류가 발생하는지, 그리고 효과적인 해결 방법은 무엇인지 상세히 알아보도록 하겠다.1. ONLY_FULL_GROUP_BY란?
ONLY_FULL_GROUP_BY는 MySQL의 엄격한 SQL 모드 중 하나이다. 이 모드가 활성화되어 있으면,GROUP BY절을 사용하는 쿼리에서SELECT리스트에 포함된 모든 컬럼은 다음 중 하나여야 한다.- 집계 함수(Aggregate Function)에 포함되어 있는 컬럼:
SUM(),COUNT(),AVG(),MIN(),MAX()와 같은 함수 내부에 사용된 컬럼이다. GROUP BY절에 명시적으로 포함되어 있는 컬럼:GROUP BY뒤에 나열된 컬럼이다.GROUP BY절에 포함된 컬럼의 함수 종속성(Functional Dependency)이 있는 컬럼: 예를 들어,id가 기본 키이고name이id에 종속적이라면,id로 그룹화할 때name을SELECT절에 포함할 수 있다. 하지만 MySQL은 이를 자동으로 파악하지 못할 때가 많으므로 명시적으로GROUP BY에 포함하는 것이 안전하다.
이 모드는 SQL 표준(SQL92 및 이후 버전)을 준수하도록 강제하여,
GROUP BY쿼리의 결과가 예측 가능하고 논리적으로 명확하도록 돕는다. 만약GROUP BY에 없는 컬럼을SELECT하면, 해당 그룹 내에서 여러 값이 존재할 수 있는데 MySQL이 어떤 값을 반환해야 할지 알 수 없기 때문에 오류를 발생시키는 것이다.2. ONLY_FULL_GROUP_BY 오류가 발생하는 이유
가장 흔한 오류 발생 시나리오는 다음과 같다.
SELECT절에 비집계 컬럼이 있지만GROUP BY에 없는 경우:
예를 들어, 어떤 테이블에서 사용자의 나이를 합산하면서 사용자의 이름을 함께 가져오려 할 때,GROUP BY절에 이름이 없으면 오류가 발생한다. 한 그룹(예: 특정 나이대) 내에 여러 이름이 있을 수 있기 때문이다.-- 오류를 발생시킬 수 있는 쿼리 예시 SELECT category_id, item_name, SUM(price) FROM products GROUP BY category_id; -- 이 쿼리에서 item_name은 GROUP BY에 없으며, SUM()으로 묶이지도 않았다.위 쿼리에서
category_id로 그룹화할 때, 한category_id에 여러item_name이 있을 수 있으므로item_name에 어떤 값을 가져와야 할지 MySQL은 판단할 수 없어 오류가 발생한다.
3. ONLY_FULL_GROUP_BY 오류 해결 방법
ONLY_FULL_GROUP_BY오류를 해결하는 방법은 크게 두 가지로 나뉜다.3.1. SQL 쿼리 자체를 수정하는 방법 (권장)
이 방법은 SQL 표준에 부합하며 데이터의 논리적 일관성을 유지하는 가장 바람직한 해결책이다. 쿼리의 목적에 따라 다음과 같이 수정할 수 있다.
SELECT절의 모든 비집계 컬럼을GROUP BY절에 추가한다.
이는 가장 직관적인 해결 방법이다.SELECT절에서 가져오고 싶은 모든 개별 컬럼을GROUP BY절에 명시적으로 추가한다.-- 해결 방법 1: GROUP BY 절에 item_name 추가 SELECT category_id, item_name, SUM(price) FROM products GROUP BY category_id, item_name;이 쿼리는
category_id와item_name의 조합별로price의 합계를 계산한다.비집계 컬럼에 적절한 집계 함수를 적용한다.
만약SELECT절의 비집계 컬럼이 각 그룹 내에서 단일한 대표 값을 가지도록 하고 싶다면,MIN(),MAX(),ANY_VALUE()(MySQL 8.0 이상)와 같은 집계 함수를 사용할 수 있다.-- 해결 방법 2: 비집계 컬럼에 집계 함수 적용 (가장 오래된/가장 작은 값을 가져옴) SELECT category_id, MIN(item_name) AS first_item_name, SUM(price) FROM products GROUP BY category_id;이 쿼리는 각
category_id그룹에서 가장 사전적으로 앞서는item_name과price의 합계를 가져온다.ANY_VALUE(item_name)를 사용하면 임의의item_name을 가져온다.
3.2. MySQL SQL 모드를 변경하는 방법 (비권장)
이 방법은 근본적인 해결책이 아니며, 데이터의 일관성을 해칠 수 있기 때문에 일반적으로 권장하지 않는다. 하지만 특정 레거시 시스템과의 호환성 등의 이유로 불가피하게 사용해야 할 때가 있을 수 있다.
세션(Session) 단위로 변경하기:
현재 MySQL 연결 세션에 대해서만ONLY_FULL_GROUP_BY모드를 비활성화한다. 애플리케이션에서 데이터베이스 연결 후 이 쿼리를 실행할 수 있다.SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));이 설정은 해당 세션이 종료되면 초기화된다.
전역(Global) 단위로 변경하기:
MySQL 서버 전체에 대해ONLY_FULL_GROUP_BY모드를 비활성화한다. 이는 MySQL 설정 파일(my.cnf또는my.ini)을 수정하여 적용하며, MySQL 서버 재시작이 필요하다.[mysqld] sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION -- 기존 sql_mode 값에서 ONLY_FULL_GROUP_BY만 제거하고 나머지는 유지하는 것이 안전하다.주의: 이 변경은 서버의 모든 데이터베이스와 애플리케이션에 영향을 미치므로 신중하게 적용해야 한다.
4. 결론
ONLY_FULL_GROUP_BY오류는 MySQL이 SQL 표준을 엄격하게 적용하여 발생하는 문제이다. 이 오류는 쿼리의 논리적 모호성을 방지하려는 의도에서 비롯된다. 가장 좋은 해결 방법은 SQL 쿼리 자체를 수정하여GROUP BY절과SELECT절의 일관성을 맞추는 것이다. 비집계 컬럼들을GROUP BY절에 추가하거나, 적절한 집계 함수를 사용하여 쿼리의 의도를 명확히 하는 것이 중요하다. SQL 모드를 변경하는 것은 임시 방편이거나 특정 상황에서만 고려해야 할 보조적인 방법이다. 쿼리 작성 시ONLY_FULL_GROUP_BY원칙을 이해하고 적용한다면, 더욱 견고하고 예측 가능한 데이터베이스 애플리케이션을 구축할 수 있을 것이다.728x90반응형'CS > DBMS' 카테고리의 다른 글
[Sequelize] `ConnectionAcquireTimeoutError` 해결: 트랜잭션과 연결 풀 관리 팁 (0) 2025.06.02 [Sequelize] `findAll` 옵션: `raw`와 `nest`는 언제 사용할까? (0) 2025.04.28 [DBMS] MySQL에서 위도, 경도 데이터 타입 어떻게 설정해야 할까? (DECIMAL 타입의 중요성) (0) 2025.04.21 [Sequelize] Sequelize timestamps의 updatedAt 업데이트, 왜 안될까? (0) 2025.03.26 [Sequelize] 새로운 테이블 추가시 발생한 문제 해결 (0) 2024.09.09 다음글이 없습니다.이전글이 없습니다.댓글 - 집계 함수(Aggregate Function)에 포함되어 있는 컬럼: