[ORACLE] SELECT문 - 그룹함수 사용 (GROUP BY, HAVING절)

hyem·2021년 7월 8일
0

ORACLE

목록 보기
2/3
post-thumbnail

그룹 함수 사용

1) 그룹 함수

행 집합 연산을 수행하여 그룹별로 하나의 결과를 산출하는 함수

  • SUM : NULL이 아닌 행들의 합계
  • AVG : NULL이 아닌 행들의 평균
  • MAX : NULL이 아닌 행들의 최댓값
  • MIN : NULL이 아닌 행들의 최솟값
  • COUNT
    • COUNT(*) : 모든 행의 수 반환
    • COUNT(컬럼명) : NULL이 아닌 값을 가진 행의 수 반환
    • COUNT(DISTINCT 컬럼명) : NULL이 아닌 값 중에서 중복을 제외하고 행의 수 반환
  • NULL인 행을 계산에 포함하고 싶을 때: NVL(컬럼명, 0)과 같이 NULL값을 0으로 만들어서 포함시킴

2) GROUP BY절

GROUP BY절을 사용하여 테이블의 행을 더 작은 그룹으로 나눌 수 있다.

  • GROUP BY절에 사용된 컬럼은 SELECT 리스트에 없어도 된다.
  • 다중 컬럼에 대해 GROUP BY 가능하다.
-- 예) "부서별", "직무별" 급여의 합을 출력하라
SELECT SUM(salary)
FROM employees
GROUP BY department_id, job_id;

위와 같이 해도 오류는 안나지만, GROUP BY절에 사용한 컬럼을 SELECT 리스트에 넣어 함께 출력해줘야 어떤 데이터인지 쉽게 알아볼 수 있다.

SELECT department_id, job_id, SUM(salary)
FROM employees
GROUP BY department_id, job_id
ORDER BY department_id;
DEPARTMENT_ID JOB_ID     SUM(SALARY)
------------- ---------- -----------
           10 AD_ASST           4400
           20 MK_MAN           13000
           20 MK_REP            6000
           30 PU_CLERK         13900
           30 PU_MAN           11000
           40 HR_REP            6500
           50 SH_CLERK         64300
           50 ST_CLERK         55700
           50 ST_MAN           36400
           60 IT_PROG          28800
           70 PR_REP           10000
           80 SA_MAN           61000
           80 SA_REP          243500
           90 AD_PRES          24000
           90 AD_VP            34000
          100 FI_ACCOUNT       39600
          100 FI_MGR           12000
          110 AC_ACCOUNT        8300
          110 AC_MGR           12000
              SA_REP            7000

	20개 행이 선택되었습니다. 
    
  • SELECT 리스트에 집계 함수를 쓴 경우, 집계 함수가 아닌 컬럼이나 표현식은 GROUP BY 절에 있어야 한다.

예) 부서별 사원수를 세서 last_name 출력하는 경우

SELECT department_id, COUNT(last_name)
FROM employees;
-- 오류 발생("not a single-group group function")
-- 아래와 같이 수정

SELECT department_id, COUNT(last_name)
FROM employees
GROUP BY department_id;

3) HAVING절

HAVING절을 사용하여 표시될 그룹을 제한할 수 있다.

  • HAVING절의 조건과 일치하는 그룹만 표시된다.
-- 예) "부서별" 급여 최대값을 출력하는데, "급여 최대값이 10000 이상인 그룹만" 출력해라.
SELECT department_id, MAX(salary)
FROM employees
GROUP BY department_id
HAVING MAX(salary) > 10000;
  • WHERE절은 그룹을 제한하는 데 사용할 수 없다!
  • WHERE절은 행 출력에 대한 조건을 명시한다
SELECT job_id, SUM(salary) AS PAYROLL
FROM employees
WHERE job_id NOT LIKE '%REP%' -- job_id 컬럼의 행들에 대한 출력 제한
GROUP BY job_id
HAVING SUM(salary) > 13000 -- 그룹에 대한 출력 제한
ORDER BY SUM(salary);

예) 부서번호가 50, 60, 80, 90중 하나이고, 부서별 급여합이 50000 이상인 부서 출력



-- (x)
SELECT department_id, SUM(salary)
FROM employees
GROUP BY department_id
HAVING SUM(salary) > 50000 AND department_id IN (50,60,80,90);

위와 같이 쓸 경우 모든 행들에 대해 부서별로 GROUP BY 한다음에 또 부서번호가 조건에 일치하는 행들을 찾아야 하므로 비효율적이다.
department_id는 그룹의 결과가 아니므로 아래와 같이 WHERE절에서 제한할 수 있다.
WHERE절에서 제한된 결과만 가지고 GROUP BY를 수행한다.

SELECT department_id, SUM(salary)
FROM employees
WHERE department_id IN (50, 60, 80, 90)
GROUP BY department_id
HAVING SUM(salary) > 50000; 

0개의 댓글