이 자료는 O'Reilly에서 나온 " Mastering Oracle SQL, 2nd Edition"을 공부하면서 몰랐던 부분을 정리하고 있습니다.
"Mastering Oracle SQL, 2nd Edition"의 저자는 Alan Beaulieu, Sanjay Mishra 이며 2004년에 나온 책이네요.
알라딘에서 구해 볼 수 있습니다.
"Mastering Oracle SQL, 2nd Edition"의 저자는 Alan Beaulieu, Sanjay Mishra 이며 2004년에 나온 책이네요.
알라딘에서 구해 볼 수 있습니다.
HAVING 절은 항상 쓰면서 따로 메뉴얼을 읽어본적은 없다.
그래서 아마 group 함수의 결과에 대해 조건을 주는거? 이렇게 생각하고 있었는데,
역시 메뉴얼을 읽어야해 ~
HAVING 절은 GROUP BY 절에 의해 나오는 나올수 있는 결과에 대해 filtering 해주는 역활을 해준다.
즉 내가 지금까지 생각하던 거와는 달리
group 함수의 결과 컬럼에 대해서만 조건을 주는 게 아니라
다음의 예를 보면 ..
부서별 인원수를 구하는 SQL이다.
SQL> select deptno,count(*) from emp group by deptno;
DEPTNO COUNT(*)
---------- ----------
30 6
20 5
10 3
이 중인 인원수가 4이상인 부서를 출력한다. 즉 group 함수에 의해 계산된 값에 대한 조건이다.
SQL> select deptno,count(*) from emp group by deptno having count(*) > 4;
DEPTNO COUNT(*)
---------- ----------
30 6
20 5
아래의 SQL은 group by 에 의해 만들어진 결과에서 deptno가 20 이상인 부서만 출력한다.
SQL> select deptno,count(*) from emp group by deptno having deptno > 20;
DEPTNO COUNT(*)
---------- ----------
30 6
그러면 group by 절에 의한 결과에 대한 having과 select 절의 where 절은 바꿔 쓸 수 있을까?
아래의 결과를 보면 having deptno > 20 과 where deptno > 20의 결과는 같다. (당연한가?)
SQL> select deptno,count(*) from emp where deptno > 20 group by deptno;
DEPTNO COUNT(*)
---------- ----------
30 6
그러나 having 절에 의한 조건은 filter 처리로 계산된 결과에서 특정 조건만을 걸러내고 있으나,
where 절의 경우 access 처리로 scan의 범위를 줄이고 있음을 알 수 있다.
SQL> select deptno,count(*) from emp group by deptno having deptno > 20;
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 6 | 3 (34)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | HASH GROUP BY | | 2 | 6 | 3 (34)| 00:00:01 |
| 3 | INDEX FAST FULL SCAN| EMP_IDX04 | 449 | 1347 | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DEPTNO">20)
SQL> select deptno,count(*) from emp where deptno > 20 group by deptno;
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 6 | 1 (0)| 00:00:01 |
| 1 | SORT GROUP BY NOSORT| | 2 | 6 | 1 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | EMP_IDX03 | 193 | 579 | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPTNO">20)
queyr의 결과는 동일하나 access 하는 범위 자체가 틀리니 이에 대한 주의가 필요하다.
당연히 access 범위를 줄일 수 있는 조건은 where 절에 기술하는 것이 유리할 듯 !!
근데, 테스트 하다보니 아래처럼 수행해도 결과가 잘 나오더군요.
select는 count를 했으나 having에는 sum으로 조건을 주어도 결과가 잘 나오네요.
SQL> select deptno,count(*) from emp group by deptno having sum(sal) > 10000;
DEPTNO COUNT(*)
---------- ----------
20 5
Execution Plan
----------------------------------------------------------
Plan hash value: 3110987654
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 28 | 13 (8)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | HASH GROUP BY | | 4 | 28 | 13 (8)| 00:00:01 |
| 3 | TABLE ACCESS FULL| EMP | 449 | 3143 | 12 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(SUM("SAL")>10000)
그럼 group by에 의한 수행 결과에 대해 조건을 주는 것이 아니라
group by에 의해 나올 수 있는 결과에 대해 조건을 줄 수 있다는 거군요..
count(*)와 sum(sal)은 operation 자체가 다른데, 이걸 다 계산하고 있다는 건가?
아니면 having에 있는 sum()이 query 수행시 참조되는 건가?
"The HAVING clause is closely associated with the GROUP BY clause. The HAVING clause is used to put a filter on the groups created by the GROUP BY clause. If a query has a HAVING clause along with a GROUP BY clause, the result set will include only the groups that satisfy the condition specified in the HAVING clause."
네, having 절에 있는 group operation도 참조되는 게 맞습니다.. ^^
SQL> select deptno from emp group by deptno having sum(sal) > 10000;
DEPTNO
----------
20
* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!
'Oracle Database' 카테고리의 다른 글
Oracle Trigger를 이용해 특정 column에 대한 변경 막기 (0) | 2010.08.11 |
---|---|
Oracle 10g에서 11g로 upgrade 할때, 기존의 hint를 삭제해야 할까요? (0) | 2010.08.09 |
ORACLE Nested Group Operations (0) | 2010.08.06 |
Oracle Table의 통계정보를 옮기는 방법. (1) | 2010.08.03 |
Oracle datafile 생성 이후 모든 archive log는 있으나 datafile의 backup이 없는 경우 recovery (0) | 2010.07.30 |