Untitled_Blue

[SQL] 그룹별 데이터의 통계 - Group by and Having 본문

Database/SQL

[SQL] 그룹별 데이터의 통계 - Group by and Having

Untitled_Blue 2023. 6. 20. 21:23
반응형

안녕하세요. 이번 글은 Group by에 대한 설명입니다.

 

- Group By Having 이란?

  • 사용자가 원하는 컬럼별로 데이터에 대한 결과값을 출력하기 위한 조건절

- 그룹화를 위한 다중행 함수

함수 설명
SUM() 칼럼값에 대한 총합을 구하는 함수
COUNT() 칼럼값에 대한 총 갯수를 구하는 함수
MIN() 칼럼값에 대한 최소값을 구하는 함수
MAX() 칼럼값에 대한 최대값을 구하는 함수
AVG() 칼럼값에 대한 평균값을 구하는 함수
COUNT(DISTINCT [칼럼명]) 칼럼값에 대한 총 갯수를 구하는데 NULL값을 제외하는 함수
select MIN(SAL), MAX(SAL), ROUND(AVG(SAL), 2), SUM(SAL), COUNT(SAL), COUNT(DISTINCT SAL) from EMP;

다음 쿼리문은 EMP 테이블에서 직원들의 급여에 대한 최소값, 최대값, 평균값, 합계, 총 갯수, 중복(또는 NULL값)을 제외한 갯수를 구하라는 뜻을 가지고 있다. 해당 쿼리문을 실행해보면 위와 같이 계산된 값이 정상적으로 출력되는 점을 확인할 수 있다.

- GROUP BY ~ HAVING

select [칼럼명], [그룹함수] 
from [테이블명] 
where [조건절] 
group by [칼럼명] 
having [그룹 조건절에 대한 조건];

이때 칼럼명을 기준으로 그룹화를 진행하기 때문에 group by 내 칼럼명과 select 내 칼럼명과 반드시 일치해야 한다. 지금부터는 몇 가지의 예제를 중심으로 설명하겠다.

1)  부서번호별 급여의 최소값과 최대값 조회

select DEPTNO, MAX(SAL), MIN(SAL) from EMP group by DEPTNO;

다음 쿼리문은 EMP 테이블에서 부서번호, 급여의 최대값과 최소값을 부서번호별로 따로 출력하라는 뜻을 가지고 있다. 쿼리문을 실행해보면 위와 같이 부서번호별로 각각의 최대 최소값을 구할 수 있는 점을 알 수 있다.

2)  부서번호별 직원 수 조회

select DEPTNO, COUNT(*) from EMP group by DEPTNO;

다음 쿼리문은 EMP 테이블에서 부서번호와 갯수를 부서번호별로 출력하라는 뜻을 가지고 있다. 쿼리문을 실행해보면 위와 같이 부서번호별 직원의 인원 수가 출력됨을 확인할 수 있다.

3) 직책별 입사날짜가 제일 먼저인 날짜와 최근인 날짜 조회

select JOB, MIN(HIREDATE), MAX(HIREDATE) from EMP group by JOB;

다음 쿼리문은 EMP 테이블에서 직책, 제일 빠른 입사날짜와 제일 최근인 입사날짜를 직책별로 출력하라는 뜻을 가지고 있다. 쿼리문을 실행해보면 위와 같이 직책별로 제일 먼저 입사한 직원의 날짜와 늦게 입사한 직원의 날짜가 따로 출력되었음을 확인할 수 있다.

4) having절 사용 - 부서번호별 제일 많은 급여값 출력하되 최대값은 2000 이상이어야 한다.

select DEPTNO, MAX(SAL) from EMP group by DEPTNO having MAX(SAL) > 2000;

다음 쿼리문은 EMP 테이블에서 부서번호, 급여의 최대값을 부서번호별로 출력하되 급여의 최대값은 2000을 초과해야 한다는 뜻을 가지고 있다. 쿼리문을 실행해보면 위와 같이 2000을 초과한 결과값이 출력되었음을 확인할 수 있다.

5) where절과 having절 누가 더 먼저일까?

select DEPTNO, JOB, MAX(SAL) from EMP where HIREDATE >= '80/01/01' group by DEPTNO, JOB having MAX(SAL) > 2000;

다음 쿼리문은 EMP 테이블에서 입사날짜가 1980년 1월 1일 이후인 직원들에 대한 부서번호, 직책과 급여의 최대값을 부서번호와 직책별로 조회하되 급여의 최대값이 2000 초과여야 한다는 뜻을 가지고 있다. 쿼리문을 실행해보면 위와 같이 부서번호별과 직책별 따로 급여의 최대값이 2000을 넘는 범위에 한해 그룹화 형식으로 정상적으로 출력되었음을 알 수 있다. 여기서 where절과 having절을 같이 사용했는데 둘 다 조건절로서 필터링한다는 점은 같다. 그러나 이 둘은 우선순위에서 차이점이 존재한다. 쿼리문을 실행할 때 where 절을 통해 우선적으로 필터링되고 그룹화 과정을 거칠 때 having 절을 통한 필터링을 거친다는 점에서 차이점을 알 수 있다.

- ROLLUP and CUBE

select [칼럼명], [그룹함수] 
from [테이블명] 
where [조건절] 
group by CUBE || ROLLUP [그룹화 대상 컬럼명1, 컬럼명2 ...];

해당 함수는 각 칼럼 별 통계를 추가로 출력하는 역할을 담당하고 있다. CUBE는 ROLLUP과 다르게 칼럼명에 대한 추가적인 통계 결과를 출력한다. 실습을 통해 알아보자.

select DEPTNO, JOB, MAX(SAL), COUNT(*) from EMP group by ROLLUP(DEPTNO, JOB);

다음 쿼리문은 EMP 테이블에서 부서번호, 직책, 급여의 최대값과 인원수를 부서번호와 직책별로 ROLLUP 함수를 통해 추가적인 통계 결과와 함께 출력하라는 뜻을 가지고 있다. 쿼리문을 실행해보면 위와 같이 부서번호와 직책별로 따로 급여에 대한 최대값과 인원수가 출력됨과 동시에 부서번호별 급여에 대한 최대값과 인원수가 출력됨을 확인할 수 있다.

select DEPTNO, JOB, MAX(SAL), COUNT(*) from EMP group by CUBE(DEPTNO, JOB);

다음 쿼리문은 EMP 테이블에서 부서번호, 직책, 급여의 최대값과 인원수를 부서번호와 직책별로 CUBE 함수를 통해 각 그룹화 대상 칼럼별 통계 결과를 추가적으로 같이 출력하라는 뜻을 가지고 있다. 쿼리문을 실행해보면 위와 같이 먼저 맨 위 첫 번째 행에 모든 칼럼과 행에 대한 결과값이 출력되는 점을 볼 수 있다. 또한 2번째 행부터 6번째 행에 각 직책별 급여의 최대값과 인원수가 출력되었음과 7, 11, 15번째 행에 각 부서번호별 급여의 최대값과 인원수가 출력되었음을 볼 수 있다. 

- GROUPING SETS

  • 그룹화 대상이 되는 모든 칼럼명에 대해서 대분류 형식으로 그룹화해서 출력하는 함수
select MGR, JOB, ROUND(AVG(SAL), 1), COUNT(*) from EMP group by GROUPING SETS(MGR, JOB);

다음 쿼리문은 EMP 테이블에서 사수의 사번, 직책, 평균 급여와 인원수를 GROUPING SETS 함수를 활용해서 사수의 사번과 직책별로 나눠서 출력하라는 뜻을 가지고 있다. 쿼리문을 실행해보면 위와 같이 직책과 사수의 사번이 대분류 형식으로 묶여서 각 칼럼에 대한 평균급여와 그에 맞는 인원수가 정상적으로 출력됨을 확인할 수 있다.

 

다음 글은 DCL에 대한 설명입니다. 감사합니다.

반응형