(데이터베이스) HAVING절과 WHERE 절의 차이

 GROUP BY 절과 HAVING 절의 특징
   - GROUP BY 절을 통해 소그룹별 기준을 정한 후, SELECT 절에 집계 함수를 사용
   - 집계 함수의 통계 정보는 NULL 값을 가진 행을 제외하고 수행한다.
   - GROUP BY 절에서는 SELECT 절과는 달리 ALIAS 명을 사용불가
   - 집계 함수는 WHERE 절에는 올 수 없다. (집계 함수를 사용할 수 있는 GROUP BY 절보다 WHERE 절이 먼저 수행)
   - WHERE 절은 전체 데이터를 GROUP으로 나누기 전에 행들을 미리 제거시킨다.
  - HAVING 절은 GROUP BY 절의 기준 항목이나 소그룹의 집계 함수를 이용한 조건을 표시할 수 있다.
  - GROUP BY 절에 의한 소그룹별로 만들어진 집계 데이터 중, HAVING 절에서 제한 조건을 두어 조건을 만족하는 내용만 출력한다.
  - HAVING 절은 일반적으로 GROUP BY 절 뒤에 위치한다.


 일부 데이터베이스의 과거 버전에서 GROUP BY 절에 명시된 칼럼의 순서대로 오름차순 정렬을 자동으로 정렬(비공식적인 지원이었음)하는 경우가 있었으나, 원칙적으로 관계형 데이터베이스 환경에서는 ORDER BY 절을 명시해야 데이터 정렬이 수행된다.
 ANSI/ISO 기준에서도 데이터 정렬에 대한 내용은 ORDER BY 절에서만 언급되어있지,  GROUP BY 절에는 언급되어 있지 않다.
예) 잘못된 쿼리-수정전
SELECT POSITION                           포지션
               ,COUNT                            인원수
               , COUNT(HEIGHT)               키대상
               , MAX(HEIGHT)                   최대키
               , MIN(HEIGHT)                     최소키
               , ROUND(AVG(HEIGHT),2) 평균키
FROM PLAYER

결과) 오류: ERROR: 단일 그룹의 집계 함수가 아니다.
GROUP BY 절에서 그룹 단위를 표시해 주어야 SELECT 절에서 그룹 단위의 칼럼과 집계 함수를 사용할 수 있다.
그렇지 않으면 예제와 같이 에러를 발생하게 된다. 

예) 잘못된쿼리-수정 후  SELECT POSITION                            포지션
               ,COUNT                            인원수
               , COUNT(HEIGHT)               키대상
               , MAX(HEIGHT)                    최대키
               , MIN(HEIGHT)                     최소키
               , ROUND(AVG(HEIGHT),2) 평균키
FROM     PLAYER
GROUP BY POSITION; 
 
ORDER BY 절이 없기때문에 포지션으로 정렬되지 않았지만 포지션 별로 인워수, 키대상, 최대키, 최소키, 평균키에 대한 그룹 내용을 출력 하고 있다. 

 

3. HAVING 절

예) 잘못된쿼리-수정전
SELECT POSITION                             포지션
               , ROUND(AVG(HEIGHT),2) 평균키
FROM     PLAYER
WHERE AVG(HEIGHT) >= 180          -- * 3행에 오류: ERROR: 집계 함수는 허가되지 않는다.
GROUP BY POSITION; 
 
위의 쿼리를 보면 POSITION 별로 평큔키가 180 이상인 사람에 대해서 출력을 하기 위해 작성 하였으나 WHERE 절에서는 집계 함수는 허가 되지 않는다.
그 이유는  먼저 WHERE 절의 조건절이 먼저 적용이 된 후 GROUP 절이 실행이 되므로 WHERE절에 있는 집계 함수는 사용 할 수 없게 된다.이때는 HAVING 절에서 집계 함수에 조건을 작성 하면 된다.
예) 잘못된쿼리-수정후
SELECT POSITION                            포지션
               , ROUND(AVG(HEIGHT),2) 평균키
FROM     PLAYER
GROUP BY POSITION;
HAVING  AVG(HEIGHT) >= 180
 
 만일 위의 쿼리에서 GROUP BY 와 HAVING 절의 순서를 바꾼다면?
 GROUP BY 절과 HAVING 절의 순서를 바꾸어서 수행하더라도 문법 에러도 없고 결과물도 동일한 결과를 출력한다.
그렇지만, SQL 내용을 보면, 포지션이란 소그룹으로 그룹핑(GROUPING)되어 통계 정보가 만들어지고, 이후 적용된 결과 값에 대한 HAVING 절의 제한 조건에 맞는 데이터만을 출력하는 것이므로 논리적으로GROUP BY 절과 HAVING 절의 순서를 지키는 것을 권고한다.
(단  SQL SERVER는 반드시 GROUP BY 와 HAVING 절의 순서를 지켜야 한다)

댓글

이 블로그의 인기 게시물

(네트워크)폴링방식 vs 롱 폴링방식

(ElasticSearch) 결과에서 순서 정렬

(18장) WebSocekt과 STOMP를 사용하여 메시징하기