이 스크립트는 {*}김강환{*}님께서 제공해주셨습니다.

{column:width=50%}


spool 2-40.lst

set timing off
set autotrace off
set linesize 1000
set pagesize 1000

prompt I. 특정 부서(AA)의 모든 입출금 내역 검색

prompt 0. 기존 테이블 삭제
drop table ACCOUNT cascade constraints purge;
drop table INPUT cascade constraints purge;
drop table OUTPUT cascade constraints purge;
drop table MONTH_DUAL cascade constraints purge;

prompt 1. 예적금원장 테이블 생성

CREATE TABLE ACCOUNT(
MANAGE_NUM VARCHAR2(10),
DEPT_COD VARCHAR2(10));

prompt 2. 예적금원장 테이블에 값 입력

INSERT INTO ACCOUNT VALUES('111','AA');
INSERT INTO ACCOUNT VALUES('222','AA');
INSERT INTO ACCOUNT VALUES('333','AA');
INSERT INTO ACCOUNT VALUES('444','BB');
INSERT INTO ACCOUNT VALUES('555','CC');

prompt 3. 입금내역 테이블 생성

CREATE TABLE INPUT(
MANAGE_NUM VARCHAR2(10),
INPUT_DATE VARCHAR2(8),
AMT NUMBER);

prompt 4. 입금내역 테이블에 값 입력

INSERT INTO INPUT VALUES('111','20060301',1000);
INSERT INTO INPUT VALUES('111','20060302',1000);
INSERT INTO INPUT VALUES('222','20060303',1000);
INSERT INTO INPUT VALUES('333','20060304',1000);
INSERT INTO INPUT VALUES('333','20060304',1000);
INSERT INTO INPUT VALUES('555','20060301',1000);
INSERT INTO INPUT VALUES('111','20060301',1000);
INSERT INTO INPUT VALUES('222','20060405',1000);
INSERT INTO INPUT VALUES('333','20060402',1000);

prompt 5. 출금내역 테이블 생성

CREATE TABLE OUTPUT(
MANAGE_NUM VARCHAR2(10),
OUTPUT_DATE VARCHAR2(8),
AMT NUMBER);

prompt 6. 출금내역 테이블 생성

INSERT INTO OUTPUT VALUES('111','20060301',1000);
INSERT INTO OUTPUT VALUES('111','20060302',1000);
INSERT INTO OUTPUT VALUES('111','20060303',1000);
INSERT INTO OUTPUT VALUES('222','20060301',1000);
INSERT INTO OUTPUT VALUES('444','20060301',1000);
INSERT INTO OUTPUT VALUES('555','20060301',1000);
INSERT INTO OUTPUT VALUES('111','20060401',1000);
INSERT INTO OUTPUT VALUES('222','20060305',1000);
INSERT INTO OUTPUT VALUES('333','20060402',1000);

prompt 7. 조인 이용한 입출금내역 조회

conn sys/loveora77 as sysdba
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SYSTEM FLUSH SHARED_POOL;

conn scott/loveora77
set timing on
set autotrace on

select inp_date, sum(inp_amt), sum(out_amt)
from ACCOUNT a,
   (select MANAGE_NUM, substr(INPUT_DATE,1,6) inp_date,
           sum(AMT) inp_amt
    from INPUT
    where INPUT_DATE between '20060301' and '20060430'
    group by MANAGE_NUM, substr(INPUT_DATE,1,6)) b,
   (select MANAGE_NUM, substr(OUTPUT_DATE,1,6) out_date,
           sum(AMT) out_amt
    from OUTPUT
    where OUTPUT_DATE between '20060301' and '20060430'
    group by MANAGE_NUM, substr(OUTPUT_DATE,1,6)) c
where b.MANAGE_NUM = a.MANAGE_NUM
  and c.MANAGE_NUM(+) = b.MANAGE_NUM
  and c.out_date(+) = b.inp_date
  and a.DEPT_COD = 'AA'
group by inp_date;


prompt 2) 정상적인 결과를 얻기 위해서 양쪽 outer join을 수행 : 임시 집합 추가해서 해결

set timing off
set autotrace off

CREATE TABLE month_dual(
COL1 date,
yyyymm varchar2(8));

INSERT INTO month_dual VALUES(systimestamp,'20060301');
INSERT INTO month_dual VALUES(systimestamp,'20060302');
INSERT INTO month_dual VALUES(systimestamp,'20060303');
INSERT INTO month_dual VALUES(systimestamp,'20060304');
INSERT INTO month_dual VALUES(systimestamp,'20060305');
INSERT INTO month_dual VALUES(systimestamp,'20060306');
INSERT INTO month_dual VALUES(systimestamp,'20060307');
INSERT INTO month_dual VALUES(systimestamp,'20060401');
INSERT INTO month_dual VALUES(systimestamp,'20060402');
INSERT INTO month_dual VALUES(systimestamp,'20060403');
INSERT INTO month_dual VALUES(systimestamp,'20060404');
INSERT INTO month_dual VALUES(systimestamp,'20060405');


prompt ② 임시 집합(x) 추가

conn sys/loveora77 as sysdba
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SYSTEM FLUSH SHARED_POOL;

conn scott/loveora77
set timing on
set autotrace on

select yyyymmdd, sum(inp_amt), sum(out_amt)
from (select MANAGE_NUM, substr(yyyymm,1,6) yyyymmdd
      from ACCOUNT a, MONTH_DUAL d
      where a.DEPT_COD = 'AA'
        and d.yyyymm between '20060301' and '20060430') x,
     (select MANAGE_NUM, substr(INPUT_DATE,1,6) inp_date, sum(AMT) inp_amt
      from INPUT
      where INPUT_DATE between '20060301' and '20060430'
      group by MANAGE_NUM, substr(INPUT_DATE,1,6)) b,
     (select MANAGE_NUM, substr(OUTPUT_DATE,1,6) out_date, sum(AMT) out_amt
      from OUTPUT
      where OUTPUT_DATE between '20060301' and '20060430'
      group by MANAGE_NUM, substr(OUTPUT_DATE,1,6)) c
where b.MANAGE_NUM(+) = x.MANAGE_NUM
  and b.inp_date(+) = x.yyyymmdd
  and c.MANAGE_NUM(+) = x.MANAGE_NUM
  and c.out_date(+) = x.yyyymmdd
group by yyyymmdd;


prompt 8. union과 group by 이용한 입출금내역 조회

conn sys/loveora77 as sysdba
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SYSTEM FLUSH SHARED_POOL;

conn scott/loveora77
set timing on
set autotrace on

select yyyymm, nvl(sum(inp_amt),0), nvl(sum(out_amt),0)
from (select MANAGE_NUM, substr(INPUT_DATE,1,6) yyyymm,
             AMT inp_amt, to_number(null) out_amt
      from INPUT
      where INPUT_DATE between '20060301' and '20060430'
     union all
      select MANAGE_NUM, substr(OUTPUT_DATE,1,6) yyyymm,
             to_number(null) inp_amt, AMT out_amt
      from OUTPUT
      where OUTPUT_DATE between '20060301' and '20060430')
group by yyyymm;


prompt 5) 잘못된 사례1. 쿼리문을 단순하게 하기 위해서 where절의 공통조건을 인라인뷰 밖으로 보낸 경우

conn sys/loveora77 as sysdba
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SYSTEM FLUSH SHARED_POOL;

conn scott/loveora77
set timing on
set autotrace on

select yyyymm, nvl(sum(inp_amt),0), nvl(sum(out_amt),0)
from (select MANAGE_NUM, substr(INPUT_DATE,1,6) yyyymm,
             AMT inp_amt, to_number(null) out_amt
    from INPUT
    union all
    select MANAGE_NUM, substr(OUTPUT_DATE,1,6) yyyymm,
           to_number(null) inp_amt, AMT out_amt
    from OUTPUT)
where yyyymm between substr('20060301',1,6) and substr('20060430',1,6)
group by yyyymm;


prompt 6) 잘못된 사례2. 형태가 다른 컬럼을 공통화시키기 위해 가공화

conn sys/loveora77 as sysdba
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SYSTEM FLUSH SHARED_POOL;

conn scott/loveora77
set timing on
set autotrace on

select substr(yyyymm,1,6), nvl(sum(inp_amt),0), nvl(sum(out_amt),0)
from (select MANAGE_NUM, INPUT_DATE yyyymm,
             AMT inp_amt, to_number(null) out_amt
      from INPUT
      union all
      select MANAGE_NUM, OUTPUT_DATE yyyymm,
             to_number(null) inp_amt, AMT out_amt
      from OUTPUT)
where yyyymm between substr('20060301',1,6) and substr('20060430',1,6)
group by substr(yyyymm,1,6);



spool off

{column}