제 1 절 고급 SQL 활용1. CASE문 활용
위 SQL은 월별납입방법별집계 테이블을 납입방법코드 분류별로 반복적으로 Access 하고 있음. I/O 효율을 고려하여 아래와 같이 수정해야 함.
2. 데이터 복제 기법 활용
<< 알티베이스 예제 스크립트 >>
데이터복제를 통한 소계 구하기
iSQL> create table copy_t(no number, no2 varchar(2));
Create success.
elapsed time : 0.00
iSQL> insert into copy_t
2 select rownum, lpad(rownum, 2, '0') from system_.sys_tables_ limit 31;
31 rows inserted.
elapsed time : 0.01
iSQL> alter table copy_t add constraint copy_t primary key(no2);
Alter success.
elapsed time : 0.02
iSQL> alter table copy_t drop primary key;
Alter success.
elapsed time : 0.01
iSQL>
iSQL>
iSQL> alter table copy_t add constraint copy_t primary key(no);
Alter success.
elapsed time : 0.00
iSQL> create unique index copy_t_no2_idx on copy_t(no2);
Create success.
elapsed time : 0.01
iSQL> select count(*) from copy_t;
COUNT
-----------------------
31
1 row selected.
elapsed time : 0.00
iSQL>
iSQL> select * from copy_t;
NO NO2
--------------------
1 01
2 02
3 03
4 04
5 05
6 06
7 07
8 08
9 09
10 10
11 11
12 12
13 13
14 14
15 15
16 16
17 17
18 18
19 19
20 20
21 21
22 22
23 23
24 24
25 25
26 26
27 27
28 28
29 29
30 30
31 31
31 rows selected.
elapsed time : 0.00
iSQL> select count(*) from employees;
COUNT
-----------------------
20
1 row selected.
elapsed time : 0.00
iSQL> select count(*)
2 from (select * from employees a, copy_t b
3 where b.no > 2);
COUNT
-----------------------
580
1 row selected.
elapsed time : 0.01
iSQL> select count(*)
2 from (select * from employees a, (select rownum no from dual connect by level <= 2) b);
COUNT
-----------------------
40
1 row selected.
elapsed time : 0.00
iSQL> select dno "부서번호"
2 , decode(no, 1, to_char(eno), 2, '부서계') "사원번호"
3 , sum(salary) "급여합계", round(avg(salary)) "급여평균"
4 from employees a, (select rownum no from dual connect by level <= 2)
5 group by dno, no, decode(no, 1, to_char(eno), 2, '부서계')
6 order by 1, 2;
부서번호 사원번호 급여합계 급여평균
-----------------------------------------------------------------------------------
1001 16 2300 2300
1001 3 2000 2000
1001 부서계 4300 2150
1002 13 980 980
1002 6 1700 1700
1002 부서계 2680 1340
1003 10 4000 4000
1003 11 2750 2750
1003 14 2003 2003
1003 15 1000 1000
1003 부서계 9753 2438
2001 17 1400 1400
2001 부서계 1400 1400
3001 4 1800 1800
3001 부서계 1800 1800
3002 1
3002 5 2500 2500
3002 부서계 2500 2500
4001 18 1900 1900
4001 8
4001 9 1200 1200
4001 부서계 3100 1550
4002 12 1890 1890
4002 19 1800 1800
4002 20
4002 7 500 500
4002 부서계 4190 1397
2 1500 1500
부서계 1500 1500
29 rows selected.
elapsed time : 0.00
iSQL> select decode(no, 3, null, to_char(dno)) "부서번호"
2 , decode(no, 1, to_char(eno), 2, '부서계', 3, '총계') "사원번호"
3 , sum(salary) "급여합계", round(avg(salary)) "급여평균"
4 from employees a, (select rownum no from dual connect by level <= 3)
5 group by decode(no, 3, null, to_char(dno))
6 , no, decode(no, 1, to_char(eno), 2, '부서계', 3, '총계')
7 order by 1, 2;
부서번호 사원번호 급여합계 급여평균
-----------------------------------------------------------------------------------------------------------------
1001 16 2300 2300
1001 3 2000 2000
1001 부서계 4300 2150
1002 13 980 980
1002 6 1700 1700
1002 부서계 2680 1340
1003 10 4000 4000
1003 11 2750 2750
1003 14 2003 2003
1003 15 1000 1000
1003 부서계 9753 2438
2001 17 1400 1400
2001 부서계 1400 1400
3001 4 1800 1800
3001 부서계 1800 1800
3002 1
3002 5 2500 2500
3002 부서계 2500 2500
4001 18 1900 1900
4001 8
4001 9 1200 1200
4001 부서계 3100 1550
4002 12 1890 1890
4002 19 1800 1800
4002 20
4002 7 500 500
4002 부서계 4190 1397
2 1500 1500
부서계 1500 1500
총계 31223 1837
30 rows selected.
elapsed time : 0.00
iSQL> select dno "부서번호"
2 , case when grouping(eno) = 1 and grouping(dno) = 1 then '총계'
3 when grouping(eno) = 1 then '부서계'
4 else to_char(eno) end "사원번호"
5 , sum(salary) "급여합계", round(avg(salary)) "급여평균"
6 from employees
7 group by rollup(dno, eno)
8 order by 1, 2;
부서번호 사원번호 급여합계 급여평균
-----------------------------------------------------------------------------------
1001 16 2300 2300
1001 3 2000 2000
1001 부서계 4300 2150
1002 13 980 980
1002 6 1700 1700
1002 부서계 2680 1340
1003 10 4000 4000
1003 11 2750 2750
1003 14 2003 2003
1003 15 1000 1000
1003 부서계 9753 2438
2001 17 1400 1400
2001 부서계 1400 1400
3001 4 1800 1800
3001 부서계 1800 1800
3002 1
3002 5 2500 2500
3002 부서계 2500 2500
4001 18 1900 1900
4001 8
4001 9 1200 1200
4001 부서계 3100 1550
4002 12 1890 1890
4002 19 1800 1800
4002 20
4002 7 500 500
4002 부서계 4190 1397
2 1500 1500
부서계 1500 1500
총계 31223 1837
30 rows selected.
elapsed time : 0.00
<< 알티베이스 예제 스크립트 >>
데이터복제를 통한 소계 구하기
iSQL> create table copy_t(no number, no2 varchar(2));
Create success.
elapsed time : 0.00
iSQL> insert into copy_t
2 select rownum, lpad(rownum, 2, '0') from system_.sys_tables_ limit 31;
31 rows inserted.
elapsed time : 0.01
iSQL> alter table copy_t add constraint copy_t primary key(no);
Alter success.
elapsed time : 0.00
iSQL> create unique index copy_t_no2_idx on copy_t(no2);
Create success.
elapsed time : 0.01
iSQL> select count(*) from copy_t;
COUNT
-----------------------
31
1 row selected.
elapsed time : 0.00
iSQL>
iSQL> select * from copy_t;
NO NO2
--------------------
1 01
2 02
3 03
4 04
5 05
6 06
7 07
8 08
9 09
10 10
11 11
12 12
13 13
14 14
15 15
16 16
17 17
18 18
19 19
20 20
21 21
22 22
23 23
24 24
25 25
26 26
27 27
28 28
29 29
30 30
31 31
31 rows selected.
elapsed time : 0.00
iSQL> select count(*) from employees;
COUNT
-----------------------
20
1 row selected.
elapsed time : 0.00
iSQL> select count(*)
2 from (select * from employees a, copy_t b
3 where b.no > 2);
COUNT
-----------------------
580
1 row selected.
elapsed time : 0.01
iSQL> select count(*)
2 from (select * from employees a, (select rownum no from dual connect by level <= 2) b);
COUNT
-----------------------
40
1 row selected.
elapsed time : 0.00
iSQL> select dno "부서번호"
2 , decode(no, 1, to_char(eno), 2, '부서계') "사원번호"
3 , sum(salary) "급여합계", round(avg(salary)) "급여평균"
4 from employees a, (select rownum no from dual connect by level <= 2)
5 group by dno, no, decode(no, 1, to_char(eno), 2, '부서계')
6 order by 1, 2;
부서번호 사원번호 급여합계 급여평균
-----------------------------------------------------------------------------------
1001 16 2300 2300
1001 3 2000 2000
1001 부서계 4300 2150
1002 13 980 980
1002 6 1700 1700
1002 부서계 2680 1340
1003 10 4000 4000
1003 11 2750 2750
1003 14 2003 2003
1003 15 1000 1000
1003 부서계 9753 2438
2001 17 1400 1400
2001 부서계 1400 1400
3001 4 1800 1800
3001 부서계 1800 1800
3002 1
3002 5 2500 2500
3002 부서계 2500 2500
4001 18 1900 1900
4001 8
4001 9 1200 1200
4001 부서계 3100 1550
4002 12 1890 1890
4002 19 1800 1800
4002 20
4002 7 500 500
4002 부서계 4190 1397
2 1500 1500
부서계 1500 1500
29 rows selected.
elapsed time : 0.00
iSQL> select decode(no, 3, null, to_char(dno)) "부서번호"
2 , decode(no, 1, to_char(eno), 2, '부서계', 3, '총계') "사원번호"
3 , sum(salary) "급여합계", round(avg(salary)) "급여평균"
4 from employees a, (select rownum no from dual connect by level <= 3)
5 group by decode(no, 3, null, to_char(dno))
6 , no, decode(no, 1, to_char(eno), 2, '부서계', 3, '총계')
7 order by 1, 2;
부서번호 사원번호 급여합계 급여평균
-----------------------------------------------------------------------------------------------------------------
1001 16 2300 2300
1001 3 2000 2000
1001 부서계 4300 2150
1002 13 980 980
1002 6 1700 1700
1002 부서계 2680 1340
1003 10 4000 4000
1003 11 2750 2750
1003 14 2003 2003
1003 15 1000 1000
1003 부서계 9753 2438
2001 17 1400 1400
2001 부서계 1400 1400
3001 4 1800 1800
3001 부서계 1800 1800
3002 1
3002 5 2500 2500
3002 부서계 2500 2500
4001 18 1900 1900
4001 8
4001 9 1200 1200
4001 부서계 3100 1550
4002 12 1890 1890
4002 19 1800 1800
4002 20
4002 7 500 500
4002 부서계 4190 1397
2 1500 1500
부서계 1500 1500
총계 31223 1837
30 rows selected.
elapsed time : 0.00
iSQL> select dno "부서번호"
2 , case when grouping(eno) = 1 and grouping(dno) = 1 then '총계'
3 when grouping(eno) = 1 then '부서계'
4 else to_char(eno) end "사원번호"
5 , sum(salary) "급여합계", round(avg(salary)) "급여평균"
6 from employees
7 group by rollup(dno, eno)
8 order by 1, 2;
부서번호 사원번호 급여합계 급여평균
-----------------------------------------------------------------------------------
1001 16 2300 2300
1001 3 2000 2000
1001 부서계 4300 2150
1002 13 980 980
1002 6 1700 1700
1002 부서계 2680 1340
1003 10 4000 4000
1003 11 2750 2750
1003 14 2003 2003
1003 15 1000 1000
1003 부서계 9753 2438
2001 17 1400 1400
2001 부서계 1400 1400
3001 4 1800 1800
3001 부서계 1800 1800
3002 1
3002 5 2500 2500
3002 부서계 2500 2500
4001 18 1900 1900
4001 8
4001 9 1200 1200
4001 부서계 3100 1550
4002 12 1890 1890
4002 19 1800 1800
4002 20
4002 7 500 500
4002 부서계 4190 1397
2 1500 1500
부서계 1500 1500
총계 31223 1837
30 rows selected.
elapsed time : 0.00
3. Union All을 활용한 M:M 관계의 조인위 두 테이블을 이용해 월별로 각 상품의 계획 대비 판매 실적을 집계하려 함. 부서별 판매계획 테이블과 채별별 판매실적은 M:M 관계.
# M:M 관계의 조인이나, Full Outer join을 Union all을 사용해 쉽게 해결 가능함. 4. 페이징 처리# 관심 종목에 대해 사용자가 입력한 거래 일시 이후 거래 데이터를 페이징 처리 방식으로 조회할 경우 가. 일반적인 페이징 처리용 SQL
나. 뒤쪽 페이지까지 자주 조회할 때
다. Union All 활용
5. 윈도우 함수 활용# 일련번호를 1씩 증가시키면서 측정값을 입력하고 , 상태 코드는 장비상태가 바뀔 때만 저장 # 상태 코드가 NULL이면 가장 최근에 상태코드가 바뀐 레코드의 값을 보여줌 select 일련번호, 측정값 ,(select max(상태코드) from 장비측정 where 일련번호 <= o.일련번호 and 상태코드 is not null) 상태코드 from 장비측정 o order by 일련번호 # 일련버호에 인덱스가 있어야 하고, [ 일련번호 + 상태코드]로 구성된 인덱스가 최적임. select 일련번호, 측정값 ,(select /*+ index_desc(장비측정 장비측정_idx) */ 상태코드 from 장비측정 where 일련번호 <= o.일련번호 and 상태코드 is not null and rownum <= 1) 상태코드 from 장비측정 o order by 일련번호 # 부분범위 처리 방식으로 앞쪽 일부만 보다가 멈출 경우 위 쿼리가 최적 select 일련번호, 측정값 ,last_value(상태코드 ignore nulls) over(order by 일련번호 rows between unbounded preceding and current row) 상태코드 from 장비측정 order by 일련번호 # 전체 결과를 다 읽어야 할 경우 위 쿼리가 최적임. # 파티션별 윈도우에서 가장 나중에 나온 값을 구함. # rows between unbounded preceding and current row : 현재 행을 포함해서 파티션 내의 마지막 행까지의 범위 지정 6. WITH 구문 활용- Materialize 방식 : 내부적으로 임시 테이블을 생성함으로써 반복 재사용 - Inline 방식 : 물리적으로 임시 테이블을 생성하지 않으며, 참조된 횟수만큼 런타임시 반복 수행. SQL문에서 반복적으로 참조되는 집합을 미리 선언함으로써 코딩을 단순화하는 용도 (인라인 뷰와는, 메인 쿼리에서 여러 번 참조가 가능하다는 점에서 다름) 알티베이스는 materialize 방식으로 작동함.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2014년 7월 10일 목요일
Using Advanced SQL
피드 구독하기:
댓글 (Atom)
댓글 없음:
댓글 쓰기