[ORACLE] GROUP BY, HAVING 절

privatekim·2024년 6월 14일
0

ORACLE

목록 보기
4/38
post-thumbnail

GROUP BY

GROUP BY절은 성격이 비슷한 칼럼데이터들을 묶어주는 절이다. 주로 테이블을 작은 행의 그룹으로 나눠준다.

GROUP BY에서 칼럼을 나누는 알고리즘은 다음 두 가지 방법이 있다.

  • SORT 알고리즘
  • HASH 알고리즘

성능적인 측면에서 HASH 알고리즘이 더욱 뛰어나기 때문에 ORACLE 9i R2버전부터 HASH 알고리즘이 적용되었다.

즉, ORACLE 9i R2이전의 버전에서는 SORT 알고리즘이 적용되었기 때문에 출력되는 결과값이 자동으로 정렬되어 나오는 것을 확인할 수 있다. 하지만, 해당 버전부터는 출력되는 결과값이 정렬되어 나오지 않는다는 것을 확인할 수 있다.

일반적으로 사용되는 문법은 다음과 같다.

select   sum(salary), department_id
from     hr.employees
GROUP by department_id
HAVING   count(department_id) > 5
ORDER BY 2;

이때 SQL문이 실행되는 작동 순서에 주의하며 아래 내용을 학습해야 한다.

SQL 작동 순서 : from -> where -> group by -> having -> select -> order by

GROUP BY절 주의점

  • NULL 포함하지 않음

  • select절에서 집계 함수에 포함되지 않은 개별 칼럼은 하나도 빠짐없이 GROUP BY절에 명시해야 한다.

-- 오류 발생
select   department_id, job_id, sum(salary)
from     hr.employees;

-- 실행 가능
select   department_id, job_id, sum(salary)
from     hr.employees
group by department_id, job_id
  • GROUP BY절에서는 열 별칭과, 위치표기법을 사용할 수 없다. (처리 순서 때문)
-- 오류 발생
select   department_id AS dept_id, job_id, sum(salary)
from     hr.employees;
group by dept_id, 2

-- 실행 가능
select   department_id, job_id, sum(salary)
from     hr.employees
group by department_id, job_id
  • WHERE절은 행을 제한하는 절이기 때문에 그룹 함수의 결과를 제한할 수 없다. 전체의 집계값인지, 부분의 집계값인지 알 수 없기 때문이다. 따라서 이러한 문제를 해결하기 위해 HAVING절을 사용한다.
-- 오류 발생
select   department_id, job_id, sum(salary)
from     hr.employees
WHERE    sum(salary) >= 10000
group by department_id, job_id

-- 실행 가능
select   department_id, job_id, sum(salary)
from     hr.employees
group by department_id, job_id
HAVING    sum(salary) >= 10000

HAVING

그룹 함수의 결과를 제한하는 절

HAVING절의 위치는 GROUP BY절의 바로 앞, 뒤에 위치할 수 있다. 하지만 일반적으로 뒤에 위치한다.

또한 SELECT문에 없는 칼럼에 대해서도 제한할 수 있다.

select   department_id, job_id, sum(salary)
from     hr.employees
where    last_name like '%i%'
group by department_id, job_id
HAVING   count(*) >= 5
order by 1;

HAVING 주의 점

개별 컬럼이 존재 할 경우 그룹 함수는 중첩을 허용하지 않는다.

--오류 발생 / 부서별 평균의 최대값을 구하는 건지, 부서별 평균의 최댓값을 구하고 싶은건지
SELECT   department_id,
		 max(round(avg(salary),2))
FROM     hr.employees
GROUP BY department_id;

-- 오류 발생
SELECT   department_id,
		 max(round(avg(salary),2))
FROM     hr.employees
GROUP BY department_id
having	 round(avg(salary),2) = max(round(avg(salary),2))
--ORA-00935: group function is nested too deeply

-- 실행 가능
SELECT   max(round(avg(salary),2))
FROM     hr.employees
GROUP BY department_id;

이러한 문제를 해결하고자 한다면, 서브쿼리를 사용해야 한다.

0개의 댓글