2014년 2월 2일 일요일

[PLSQL,SQL교육강좌, 구로디지털단지오라클교육]SQL WHERE 와 HAVING 구로디지털 오엔제이프로그래밍실무교육센터

[PLSQL,SQL교육강좌, 구로디지털단지오라클교육]SQL WHERE  HAVING
 
구로디지털 오엔제이프로그래밍실무교육센터
www.onjprogramming.co.kr
 
 
 
예문을 통해 WHERE를 쓰는 경우와 HAVING을 쓰는 경우의 차이에 대해 알아 보도록 하겠습니다.
 
n  실습을 위한 테이블을 만들자.
 
create table myemp1
(empno number not null primary key,
 ename varchar2(100),
 deptno number,
 addr   varchar2(100),
 sal    number
 )
 
-- 실습을 위해 myemp1 2000만건 만들자.
DECLARE
          v_c NUMBER := 1;
BEGIN
 
          WHILE (v_c <= 10000000) LOOP
                insert into myemp1 values ( v_c, '홍길동'||v_c, mod(v_c, 5), '서울'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
                insert into myemp1 values ( v_c, '다길동'||v_c, mod(v_c, 5), '부산'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
                insert into myemp1 values ( v_c, '나길동'||v_c, mod(v_c, 5), '대구'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
                insert into myemp1 values ( v_c, '나길동'||v_c, mod(v_c, 5), '광주'||v_c, mod(v_c, 1000000));
                v_c := v_c + 1;
          END LOOP;
          commit;
END;
 
create index idx_myemp1_deptno on myemp1(deptno)
 
 
 
SQL> set autotrace on explain
SQL> set timing on
 
아래 질의는 MYEMP1 테이블의 데이터를 DEPTNO 별로 그룹핑 하는데DEPTNO 1번인 부서원들의 급여 합을 구하는 질의 입니다. (myemp1에는 dept인덱스가 걸려 있습니다)
 
 10초 가까지 걸렸다.
 
SQL> select deptno, avg(sal)
  2    from myemp1
  3   group by deptno
  4   having deptno  = 1;
 
    DEPTNO   AVG(SAL)
---------- ----------
1       499998.5
 
   : 00:00:09.89
--------------------------------------
| Id  | Operation           | Name   |
--------------------------------------
|   0 | SELECT STATEMENT    |        |
|*  1 |  FILTER             |        |
|   2 |   SORT GROUP BY     |        |
|   3 |    TABLE ACCESS FULL| MYEMP1 |
 
 
 
이 경우에는 Table FULL SCAN한 후 GROUP BY를 한 후 deptno 1인 것을 찾기 위해 FILTER를 사용 했습니다.
 
 
이 번에는 having 대신 where절을 이용하여 같은 결과를 만들어 보도록 하겠습니다.
(현재 deptno 값은 0,1,2,3,4 5가지 값이 있어 분포도가 20%)
 
17초 정도 결렸다아마 데이터가 많아서 그런 모양이다테스트 해보라.
 
SQL>  select deptno, avg(sal)
  2     from myemp1
  3   where deptno =1
  4  group by deptno;
 
    DEPTNO   AVG(SAL)
---------- ----------
         1   499998.5
 
   : 00:00:17.29
 
Execution Plan
----------------------------------------------------------
|   0 | SELECT STATEMENT             |                   |
|   1 |  SORT GROUP BY               |                   |
|   2 |   TABLE ACCESS BY INDEX ROWID| MYEMP1            |
|*  3 |    INDEX RANGE SCAN          | IDX_MYEMP1_DEPTNO |
----------------------------------------------------------
 
이 경우에는 DEPTNO의 인덱스를 이용하여 부분 검색을 통해 deptno 10인 데이터를 꺼낸 후 GROUP BY를 시켜 count(*)를 구하였습니다.
 
 
이번에는 위 SQL문을 hash_sj(해시세미조인)을 시켜보자절반 정도 빨라진다.
 
SQL> select deptno, avg(sal)
  2    from myemp1
  3  where deptno =1
  4   group by deptno;
 
    DEPTNO   AVG(SAL)
---------- ----------
         1   499998.5
 
   : 00:00:08.43
 
Execution Plan
----------------------------------------------------------
|   0 | SELECT STATEMENT     |        |  2339K|    58M| 16991   (1)|
|   1 |  SORT GROUP BY NOSORT|        |  2339K|    58M| 16991   (1)|
|*  2 |   TABLE ACCESS FULL  | MYEMP1 |  2339K|    58M| 16991  (1)|
 
 
 
아래처럼 집계된 값이 어떠하다라고 비교 할려면 반드시 having구만을 사용해야 합니다.
 
 
SQL>  select deptno, avg(sal)
  2     from myemp1
  3    group by deptno
  4    having avg(sal) > 300000;
 
    DEPTNO   AVG(SAL)
---------- ----------
         0   499997.5
         1   499998.5
         2   499999.5
         3   500000.5
         4   500001.5
 
   00:00:09.64
 
Execution Plan
-----------------------------------------------
Plan hash value: 2438610968
 
--------------------------------------
| Id  | Operation           | Name   |
--------------------------------------
|   0 | SELECT STATEMENT    |        |
|*  1 |  FILTER             |        |
|   2 |   SORT GROUP BY     |        |
|   3 |    TABLE ACCESS FULL| MYEMP1 |

댓글 없음:

댓글 쓰기