[SQL] GROUP BY, HAVING절

1. 집계함수(AGGREGATE FUNCTION)

  • 여러 행들의 그룹이 모여 그룹당 하나의 결과를 리턴하는 함수
  • GROUP BY 절은 행들을 소그룹화 함
  • SELECT절, HAVING절, ORDER BY 절에 사용할 수 있음.

집계함수명([DISTINCT] 칼럼이나 표현식)

COUNT(*)

  • NULL값을 포함한 행의 수 출력

    COUNT(표현식)

  • 표현식의 값이 NULL값을 제외한 행의 수 출력

    SUM([DISTINCT] 표현식)

  • NULL값을 제외한 합계출력

    AVG([DISTINCT] 표현식)

  • NULL값을 제외한 평균출력

    MAX([DISTINCT] 표현식)

  • 표현식의 최대값 출력

    MIN([DISTINCT] 표현식)

  • 표현식의 최소값 출력

    STDDEV([D] 표현식)

  • 표현식의 표준편차 출력

    VARIAN([D] 표현식)

  • 표현식의 분산 출력

2. GROUP BY절

  • SQL문에서 FROM과 WHERE절 뒤에 위치, 데이터를 그룹으로 분류하여 소그룹에대한 항목별 통계정보를 얻을때 사용
1
2
3
4
5
SELECT [DISTINCT] 칼럼명 [ALIAS명]
FROM 테이블명
[WHERE 조건식]
[GROUP BY 칼럼이나 표현식]
[HAVING 그룹조건식];

GROUP BY, HAVING절의 특성

  • 그룹바이로 소그룹의 기준을 정한후, SELECT 절에 집계함수를 사용
  • 집계함수의 통계정보는 NULL값을 제외하고 수행함
  • WHERE절에는 집계함수 올 수 없음
  • HAVING절은 그룹바이절의 기준 항목이나 소그룹의 집계함수를 이용한 저건을 표시
  • 그룹바이절에 의해 소그룹별로 만들어진 집계데이터 중, HAVING 절에 제한 조건을 두어 만족하는 내용만 출력
  • HAVING절은 일반적으로 GROUP BY절 뒤에 위치
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT POSITION 포지션, AVG(HEIGHT) 평균키
FROM PLAYER;
-->>ERROR : 단일 그룹의 집계함수가 아니다라고 나옴


SELECT POSITION 포지션, AVG(HEIGHT) 평균키
FROM PLAYER
GROUP BY POSITION 포지션;
-->>ERROR SQL명령어가 올바르게 종료되지 않음-->그룹바이에 별명ALIAS쓸 수 없음

--포지션별 최대키, 최소키, 평균키 출력
SELECT POSITION 포지션, MAX(HEIGHT), MIN(HEIGHT), AVG(HEIGHT)
FROM PLAYER
GROUP BY PISITION;

3.HAVING 절

  • GROUP BY후에 조건을 달고 싶을때 WHERE 대신 씀
  • WHERE절은 GROUP BY절 전에 오기때문에 소그룹으로 묶인후의 조건을 걸 수없음.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SELECT POSITION 포지션, ROUND(AVG(HEIGHT),2) 평균키
FROM PLAYER
WHERE AVG(HIGHT) >=180
GROUP BY POSITION
--3행오류 : 집계함수가 허가되지 않음. 그룹바이로 소그룹화 되기전에 집계함수를 사용했기때문.

SELECT POSITION, ROUND(AVG(HEIGHT),2)
FROM PLAYER
GROUP BY POSITION
HAVING AVG(HEIGNT)>=180;

--이렇게써야함
--예제)
--최대 키가 190CM이상인 선수를 가지고 포지션별 평균 키를 출력
SELECT POSICITON AVG(HEIGHT)
FROM PLAYER
GROUP BY POSITION
HAVING MAX(HEIGHT) >=190;

4. CASE 표현을 활용한 월별 데이터 집계

  • 모델링의 제 1정규화로 반독되는 칼럼의 경우, 구분칼럼을 두고 여러개의 레코드로 만들어진 집합을 정해진 칼럼 수만큼 확장해서 집계 보고서를 만드는 유용한 기법

예제)
부서별 월별 입사자의 평균 급여를 조회, 입사후 1년마다 급여 인상이나 보너스 지급과 같은 일정이 정기적으로 잡히면 업무적으로 중요한 정보가 됨

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
--STEPT1
--개별입사정보에서 월별데이터 추출
SELECT ENAME, DEPOTNO, EXTRACT(MONTH FROM HIREDATE) MONTH, SAL
FROM EMP;

--STEPT2 월별데이터 구분
SELECT ENAME, DEPTNO,
CASE MONTH WHEN 1 THEN SAL END M01, CASE MONTH WHEN 2 THEN SAL END M02,
CASE MONTH WHEN 3 THEN SAL END M03, CASE MONTH WHEN 4 THEN SAL END M04,
CASE MONTH WHEN 5 THEN SAL END M05, CASE MONTH WHEN 6 THEN SAL END M06,
CASE MONTH WHEN 7 THEN SAL END M07, CASE MONTH WHEN 8 THEN SAL END M08,
CASE MONTH WHEN 9 THEN SAL END M09, CASE MONTH WHEN 10 THEN SAL END M10,
CASE MONTH WHEN 11 THEN SAL END M11, CASE MONTH WHEN 12 THEN SAL END M12
FROM (SELECT ENAME, DEPTNO, EXTRACT(MONTH FROM HIREDATE) MONTH, SAL
FROM EMP);

--STEPT3 2의구분을 부서별로 그룹화
SELECT DEPTNO,
AVG(CASE MONTH WHEN 1 THEN SAL END) M01, AVG(CASE MONTH WHEN 2 THEN SAL END) M02,
AVG(CASE MONTH WHEN 3 THEN SAL END) M03, AVG(CASE MONTH WHEN 4 THEN SAL END) M04,
AVG(CASE MONTH WHEN 5 THEN SAL END) M05, AVG(CASE MONTH WHEN 6 THEN SAL END) M06,
AVG(CASE MONTH WHEN 7 THEN SAL END) M07, AVG(CASE MONTH WHEN 8 THEN SAL END) M08,
AVG(CASE MONTH WHEN 9 THEN SAL END) M09, AVG(CASE MONTH WHEN 10 THEN SAL END) M10,
AVG(CASE MONTH WHEN 11 THEN SAL END) M11, AVG(CASE MONTH WHEN 12 THEN SAL END) M12
FROM (SELECT ENAME, DEPTNO, EXTRACT(MONTH FROM HIREDATE) MONTH, SAL
FROM EMP)
GROUP BY DEPTNO;

5.집계함수와 NULL처리

  • 빈칸을 NULL이 아니라 0으로 처리하기 위해 NVL()을 사용하는 경우가 있는데, 오히려 불필요할 수 있음
  • 행 함수는 건수가 NULL인 행을 빼고 계산함. SUM, AVG,..등 굳이 0을넣어 불필요하게 더 계산할 필요가 없음
  • ELSE 절 생략하면 DEFAULT 값이 NULL임
  • 출력시 NULL이 아닌 0을 표현하고싶으면 NVL(SUM(SAL),0)이렇게 하면됨
# sql

댓글

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×