행 집합 연산을 수행하여 그룹별로 하나의 결과를 산출하는 함수
SUM
: NULL이 아닌 행들의 합계 AVG
: NULL이 아닌 행들의 평균 MAX
: NULL이 아닌 행들의 최댓값MIN
: NULL이 아닌 행들의 최솟값COUNT
COUNT(*)
: 모든 행의 수 반환COUNT(컬럼명)
: NULL이 아닌 값을 가진 행의 수 반환COUNT(DISTINCT 컬럼명)
: NULL이 아닌 값 중에서 중복을 제외하고 행의 수 반환NVL(컬럼명, 0)
과 같이 NULL값을 0으로 만들어서 포함시킴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개 행이 선택되었습니다.
예) 부서별 사원수를 세서 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;
HAVING절을 사용하여 표시될 그룹을 제한할 수 있다.
-- 예) "부서별" 급여 최대값을 출력하는데, "급여 최대값이 10000 이상인 그룹만" 출력해라.
SELECT department_id, MAX(salary)
FROM employees
GROUP BY department_id
HAVING MAX(salary) > 10000;
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;