ORA-00979란?
ORA-00979는 Oracle SQL에서 GROUP BY 절을 사용할 때 SELECT 절에 포함된 컬럼이나 표현식이 GROUP BY 절에 명시되지 않았을 때 발생하는 에러입니다. Oracle의 SQL 표준 규칙에 따르면, GROUP BY를 사용하는 쿼리에서 SELECT 절에 포함되는 모든 컬럼은 반드시 집계 함수(SUM, COUNT, MAX, MIN, AVG 등)로 감싸거나 GROUP BY 절에 명시되어야 합니다. 이 에러는 주로 복잡한 집계 쿼리를 작성하거나, 기존 쿼리를 수정하는 과정에서 컬럼을 추가하면서 GROUP BY 절을 업데이트하지 않았을 때 빈번하게 발생합니다.
주요 발생 원인
1. SELECT 절의 컬럼이 GROUP BY 절에 누락된 경우
가장 일반적인 원인으로, SELECT 절에 여러 컬럼을 나열했지만 일부 컬럼을 GROUP BY 절에 포함시키지 않은 경우입니다. 특히 쿼리를 수정하면서 새로운 컬럼을 SELECT에 추가했지만 GROUP BY를 수정하지 않았을 때 자주 발생합니다.
2. 표현식(Expression)이 GROUP BY와 정확히 일치하지 않는 경우
SELECT 절에서 사용한 표현식(예: TRUNC(order_date, 'MM'))이 GROUP BY 절의 표현식과 정확히 동일하지 않은 경우 에러가 발생합니다. Oracle은 표현식의 완전한 일치를 요구하기 때문에 대소문자나 공백까지도 영향을 줄 수 있습니다.
3. 서브쿼리 또는 인라인 뷰 내부의 GROUP BY 누락
메인 쿼리는 올바르게 작성되었더라도, 서브쿼리나 인라인 뷰 내부에서 집계를 처리하는 과정에서 해당 에러가 발생할 수 있습니다. 중첩된 쿼리 구조에서는 각 쿼리 레벨마다 GROUP BY 규칙이 독립적으로 적용됩니다.
4. HAVING 절과 GROUP BY의 컬럼 불일치
HAVING 절에서 참조하는 컬럼이 GROUP BY에 없거나 집계 함수로 감싸지지 않은 경우에도 동일한 에러가 발생할 수 있습니다. HAVING 절은 그룹에 대한 필터링을 수행하므로, GROUP BY에 명시된 컬럼이나 집계 함수만 사용 가능합니다.
5. 조인(JOIN) 후 집계 시 컬럼 관리 실수
여러 테이블을 조인한 뒤 집계 쿼리를 작성할 때, 조인된 테이블의 컬럼을 SELECT에 추가하면서 GROUP BY 절에 해당 컬럼을 빠뜨리는 경우가 많습니다. 조인 결과에는 컬럼 수가 많아지기 때문에 실수가 발생하기 쉽습니다.
해결 방법
해결책 1: 누락된 컬럼을 GROUP BY 절에 추가
가장 기본적인 해결 방법입니다. SELECT 절에 있는 집계 함수가 아닌 모든 컬럼을 GROUP BY에 추가합니다.
-- 에러 발생 쿼리
SELECT department_id, job_id, SUM(salary)
FROM employees
GROUP BY department_id;
-- ORA-00979: not a GROUP BY expression 발생 (job_id 누락)
-- 해결된 쿼리
SELECT department_id, job_id, SUM(salary)
FROM employees
GROUP BY department_id, job_id;
해결책 2: 집계가 불필요한 컬럼은 SELECT에서 제거
해당 컬럼이 분석에 꼭 필요하지 않다면, SELECT에서 제거하는 것도 올바른 해결책입니다.
-- 에러 발생 쿼리
SELECT department_id, employee_name, COUNT(*) AS emp_count
FROM employees
GROUP BY department_id;
-- 해결 방법 1: GROUP BY에 추가
SELECT department_id, employee_name, COUNT(*) AS emp_count
FROM employees
GROUP BY department_id, employee_name;
-- 해결 방법 2: 필요 없는 컬럼 제거
SELECT department_id, COUNT(*) AS emp_count
FROM employees
GROUP BY department_id;
해결책 3: 표현식을 GROUP BY와 정확히 일치시키기
SELECT 절에서 사용하는 표현식과 GROUP BY 절의 표현식이 완전히 동일해야 합니다.
-- 에러 발생 쿼리
SELECT TRUNC(hire_date, 'MM') AS hire_month, COUNT(*) AS cnt
FROM employees
GROUP BY hire_date;
-- ORA-00979: 표현식 불일치
-- 해결된 쿼리: 동일한 표현식 사용
SELECT TRUNC(hire_date, 'MM') AS hire_month, COUNT(*) AS cnt
FROM employees
GROUP BY TRUNC(hire_date, 'MM');
-- 실무 예: 월별 매출 집계
SELECT
TO_CHAR(order_date, 'YYYY-MM') AS order_month,
product_category,
SUM(sale_amount) AS total_sales,
COUNT(*) AS order_count
FROM sales
GROUP BY
TO_CHAR(order_date, 'YYYY-MM'),
product_category
ORDER BY order_month, product_category;
해결책 4: 서브쿼리를 활용하여 구조 분리
GROUP BY 대상이 아닌 컬럼이 꼭 필요한 경우, 서브쿼리나 인라인 뷰를 활용하여 집계와 조회를 분리합니다.
-- 에러 발생 쿼리: 부서별 최고 급여자의 이름을 함께 표시하려 할 때
SELECT department_id, first_name, MAX(salary)
FROM employees
GROUP BY department_id;
-- ORA-00979 발생
-- 해결된 쿼리: 서브쿼리와 조인 활용
SELECT
e.department_id,
e.first_name,
e.salary
FROM employees e
JOIN (
SELECT department_id, MAX(salary) AS max_salary
FROM employees
GROUP BY department_id
) dept_max
ON e.department_id = dept_max.department_id
AND e.salary = dept_max.max_salary
ORDER BY e.department_id;
해결책 5: HAVING 절 수정
HAVING 절에서도 동일한 규칙이 적용됩니다.
-- 에러 발생 쿼리
SELECT department_id, SUM(salary) AS total_sal
FROM employees
GROUP BY department_id
HAVING job_id = 'IT_PROG';
-- ORA-00979: job_id는 GROUP BY에 없고 집계 함수도 아님
-- 해결 방법 1: WHERE 절로 이동 (그룹화 전 필터링)
SELECT department_id, SUM(salary) AS total_sal
FROM employees
WHERE job_id = 'IT_PROG'
GROUP BY department_id;
-- 해결 방법 2: job_id를 GROUP BY에 추가
SELECT department_id, job_id, SUM(salary) AS total_sal
FROM employees
GROUP BY department_id, job_id
HAVING job_id = 'IT_PROG';
해결책 6: 복잡한 조인 쿼리에서의 처리
-- 에러 발생 쿼리: 부서명을 포함한 급여 집계
SELECT
d.department_name,
e.department_id,
e.job_id,
SUM(e.salary) AS total_salary
FROM employees e
JOIN departments d ON e.department_id = d.department_id
GROUP BY e.department_id;
-- ORA-00979: department_name, job_id 누락
-- 해결된 쿼리
SELECT
d.department_name,
e.department_id,
e.job_id,
SUM(e.salary) AS total_salary
FROM employees e
JOIN departments d ON e.department_id = d.department_id
GROUP BY d.department_name, e.department_id, e.job_id
ORDER BY e.department_id, e.job_id;
예방 방법
1. SELECT 절 작성 후 GROUP BY를 체계적으로 검토하는 습관
쿼리 작성 시 SELECT 절을 먼저 완성한 뒤, 집계 함수가 아닌 모든 컬럼과 표현식을 그대로 복사하여 GROUP BY 절에 붙여넣는 방식을 사용하면 누락을 방지할 수 있습니다. 특히 컬럼 수가 많은 쿼리에서 매우 효과적인 방법입니다.
2. 쿼리 리뷰 시 SELECT-GROUP BY 매핑 테이블 작성
복잡한 집계 쿼리를 작성할 때는 각 컬럼이 집계 함수로 처리되는지, GROUP BY에 포함되는지를 명시적으로 정리하는 습관을 들이세요. 코드 리뷰 시에도 다른 팀원이 쉽게 검토할 수 있어 유지보
Top comments (0)