집합 지향적인 사고
가 좋음SQL은 반복문이 없음
# sign 함수: 숫자 자료형 매개변수
# 음수 -> -1
# 양수 -> 1
# 0 -> 0
# rows between n preceding and n preceding: 대상 범위 레코드를 직전 n개 이전 부터 n개 이전까지의 레코드 범위로 제한
insert into sales2
select company, year, sale,
case sign(sale - max(sale) over (partition by company
order by year
rows between 1 preceding and 1 preceding))
when 0 then '='
when 1 then '+'
when -1 then '-'
else null end as var
from sales;
# 윈도우 함수를 정렬 실행
SELECT STATEMENT
WINDOW SORT
TABLE ACCESS FULL
create table postal_code (
pcode char(7),
distinct_name varchar(256),
constraint pk_pcode primary key(pcode)
);
insert into postal_code values ('4130001', '제주특별자치도 서귀포시');
select pcode, distinct_name,
case when pcode = '410033' then 0
when pcode like '413003%' then 1
when pcode like '41300%' then 2
when pcode like '4130%' then 3
when pcode like '413%' then 4
when pcode like '41%' then 5
when pcode like '4%' then 6
else null
end as rank
from postal_code;
select *
from postal_code
where case when pcode = '410033' then 0
when pcode like '413003%' then 1
when pcode like '41300%' then 2
when pcode like '4130%' then 3
when pcode like '413%' then 4
when pcode like '41%' then 5
when pcode like '4%' then 6
else null
end =
(select min(case when pcode = '410033' then 0
when pcode like '413003%' then 1
when pcode like '41300%' then 2
when pcode like '4130%' then 3
when pcode like '413%' then 4
when pcode like '41%' then 5
when pcode like '4%' then 6
else null end)
from postal_code);
SELECT STATEMENT
TABLE ACCESS FULL
SORT AGGREGATE
TABLE ACCESS FULL
select *
from (select pcode, distinct_name,
case when pcode = '410033' then 0
when pcode like '413003%' then 1
when pcode like '41300%' then 2
when pcode like '4130%' then 3
when pcode like '413%' then 4
when pcode like '41%' then 5
when pcode like '4%' then 6
else null end as hit_code,
min(case when pcode = '410033' then 0
when pcode like '413003%' then 1
when pcode like '41300%' then 2
when pcode like '4130%' then 3
when pcode like '413%' then 4
when pcode like '41%' then 5
when pcode like '4%' then 6
else null end)
over(order by case when pcode = '410033' then 0
when pcode like '413003%' then 1
when pcode like '41300%' then 2
when pcode like '4130%' then 3
when pcode like '413%' then 4
when pcode like '41%' then 5
when pcode like '4%' then 6
else null end) as min_code
from postal_code) foo
where hit_code = min_code;
테이블 접근 1회
윈도우 함수 사용으로 정렬 알고리즘 사용
테이블 크기가 클 때, 정렬 알고리즘의 혜택으로 풀 스캔보다 스캔 범위를 줄여줌
SELECT STATEMENT
VIEW
WINDOW SORT
TABLE ACCESS FULL
recursive union : 재귀 연산
계층 구조 깊이를 사전에 모르는 경우에도 사용 가능
재귀에 사용하는 explosion 뷰는 일시 테이블로 만듬
일시테이블(explosion) + 원본 테이블(postal_history)는 인덱스를 사용해 nested loops 수행
with recursive explosion (name, pcode, new_pcode, depth)
as
(select name, pcode, new_pcode, 1
from postal_history
where name = 'a' and new_pcode is null
union
select child.name, child.pcode, child.new_pcode, depth+1
from explosion as parant, postal_history as child
where parent.pcode = child.new_pcode and parent.name = child.name);
select name, pcode, new_pcode
from explosion
where depth = (select max(depth) from explosion);
갱신 거의 없는 경우 유리한 모델
각 레코드 데이터를 집합으로 봄
계층 구조를 집합 중첩관계로 표현
name | pcode | lft | rgt |
---|---|---|---|
a | 413001 | 0 | 27 |
a | 413002 | 9 | 18 |
b | 413103 | 0 | 27 |
b | 413104 | 8 | 17 |
데이터를 수치선 상에 존재하는 원으로 사고
좌표값은 대소 관계만 만족하면 실수값도 사용 가능
이사할 때마다 새로운 우편번호가 이전 우편번호 안에 포함되는 형태로 추가
새로 추가되는 우편번호 좌표
가장 오래된 주소는 가장 바깥쪽에 있는 원 찾으면 됨.
다른 원에 포함되지 않는 원
not exist 활용
select name, pcode
from postal_history ph1
where name = 'a'
and not exists
(select * from postal_history ph2
where ph2.name = 'a'
and ph1.lft > ph2.lft);
SELECT STATEMENT
NESTED LOOPS ANTI
TABLE ACCESS BY INDEX ROWID # postal_history2
INDEX RANGE SCAN # pk_name_pcode2
TABLE ACCESS BY INDEX ROWID # postal_history2
INDEX RANGE SCAN # uq_name_lft
애플리케이션 (절차 지향형) |
---|
SQL (집합 지향형) |
실행계획 (절차 지향형) |
<>
: 임시 테이블
좋은 글 감사합니다! 키워드 별로 잘 정리해주셔서 읽는데 너무 편했습니다.👍
글을 읽으니 SQL 레벨업 공부를 해보고 싶어지네요..
행복한 하루 되세요~😁😁😁