select * from LP회원 where 회원번호 in (01')
select * from LP회원 where 회원번호 in (01', '02')
select * from LP회원 where 회원번호 in (01', '03')
select * from LP회원 where 회원번호 in (01', '02', '03')
select * from LP회원 where 회원번호 in (02')
select * from LP회원 where 회원번호 in (02', '03')
select * from LP회원 where 회원번호 in (03')
선택 가능한 회원수가 4개로 늘어나면 15개, 5개변 31개의 SQL이 필요함. Dynamic SQL을 사용하는 손쉬운 방법을 선택하게 됨.
select * from LP회원 where 회원번호 in ( :a, :b, :c )
select * from LP회원
where 회원번호 in ( decode(:a, 'all', '01', :b)
, decode(:a, 'all', '02', :c)
, decode(:a, 'all', '03', :d) )
select * from 수시공시내역
where 공시일자 = :일자
and :inlist like '%' || 분류코드 || '%'
select * from 수시공시내역
where 공시일자 = :일자
and INSTR(:inlist, 분류코드) > 0
문자열을 처리하는 오라클 내부 알고리즘상 like 연산자보다 instr 함수를 사용하면 더 빠르므로 아래와 같이 작성할 것을 권고
select * from 수시공시내역
where 공시일자 = :일자
and 분류코드 in ( ... )
select * from 수시공시내역
where 공시일자 = :일자
and INSTR(:inlist, 분류코드) > 0
인텍스 구성이 분류코드 + 공시일자일 때는 당연히 1번이 유리, 2번은 인텍스를 사용하지 못하거나 Index Full Scan
하지만 인텍스 구성이 공시일자 + 분류코드일 때는 항목 개수가 소수일 경우 1번이 유리, 다수일 경우 2번이 유리 할 수도 있다.(인덱스 깊이와 데이터 분포에 따라)
select /*+ ordered use_nl(B) */ B.*
from ( select 분류코드
from 수시공시분류
where INSTR(:inlist, 분류코드) > 0 ) A
, 수시공시내역 B
where B.분류코드 = A.분류코드
se1ect /*+ ordered use n1(B) */ B.*
frαn (se1ect substr( : in1ist, (rownum-1) * 2+1, 2)
from 수시공시분류
where rownum <= 1ength ( :inlist) / 2) A
' 수시공시내역 B
where B . 분류코드 A . 분류코드
select /*+ ordered use nl (B) */ B.*
from (select substr (: inlist, (level-l )*2+1, 2)
from dual
connect by level <= length( :inlist) / 2) A
, 수시공시내역 B
where B . 분류코드 A. 분류코드
select 회원번호, SUM(체결건수), SUM(체결수량), SUM(거래대금)
from 일별거래실적 e
where 거래일자 = :trd_dd
and 시장구분 = '유가'
and exists (
select 'x'
from 종목
where 종목코드 = e.종목코드
and 코스피종목편입여부 = 'Y'
)
group by 회원번호
Static SQL
select 회원번호, SUM(체결건수), SUM(체결수량), SUM(거래대금)
from 일별거래실적 e
where 거래일자 = :trd_dd
and 시장구분 = '유가'
and exists (
select 'x'
from 종목
where 종목코드 = e.종목코드
and 코스피종목편입여부 = decode(:check_yn, 'Y', 'Y', 코스피종목편입여부)
)
group by 회원번호
코스피 종목 편입 여부와 상관없이 전 종목을 집계시에는 서브쿼리 수행할 필요가 없다. SQL을 무리하게 통합함으로써 항상 서브쿼리 수행이라는 비효율적 결과를 안게 됨.
전 종목을 대상으로 집계하고자 할 때 블록 I/O가 8518 발생
시용자가 코스피 편입 종목만으로 집계하고자 할 때] 블록 I/O가 8208 발생
select 회원번호, SUM(체결건수), SUM(체결수량), SUM(거래대금)
from 일별거래실적 e
where 거래일자 = :trd_dd
and 시장구분 = '유가'
and exists (
select 'x' from dual where :check_yn = 'N'
union all
select 'x'
from 종목
where 종목코드 = e.종목코드
and 코스피종목편입여부 = 'Y'
and :check_yn = 'Y'
)
group by 회원번호
Exists 서브쿼리는 존재여부만 체크하는 것이므로 그 안에 union all을 사용하면 조인에 성공하는 첫 번째 레코드를 만나는 순간 더는 진행하지 않고 true를 리턴한다.
전 종목을 대상으로 집계하고자 할 때
union all 아래쪽 종목 태이블과는 조인을 시도하지 않고 곧바로 Exists 서브쿼리를 빠져 나온다. 1Og부터 DUAL 테이블은 FASTDUAL 방식으로 수행되기 때문에 블록 1/0는 발생하지 않는다.
사용지가 표스피 편입 종목만으로 집계하고자 할 때
동일한 성능
/* 1 : 평균 2: 합계 */
if( pfmStrCmpTrim(INPUT->inData.gubun, "1", 1) == 0){
snprintf(..., " avg(계약수), avg(계약금액), avg(미결제약정금액) ");
} else {
snprintf(..., " sum(계약수), sum(계약금액), sum(미결제약정금액) ");
}
/* 1 : 평균 2: 합계 */
decode(:gubun, '1', avg(계약수), sum(계약수)),
decode(:gubun, '1', avg(계약금액), sum(계약금액)),
decode(:gubun, '1', avg(미결재약정금액), sum(미결재약정금액)),
Decode, Case 이용
where 거래미형성률 between :min1 and :max1
and 일평균거래량 between :min2 and :max2
and 일평균거래대금 between :min3 and :max3
and 호가스프레드비율 between :min4 and :max4
and 가격연속성 between :min5 and :max5
and 시장심도 between :min6 and :max6
and 거래체결률 between :min7 and :max7
거래량 도메인은 9자리 숫자형이고 정수 값만 허용하므로 입력 가능한 최소값은 0 최대값은 999.999.999이다.
따라서 시용자가 1000주를 입력하면 사용자가 선택한 비교 연산자에 따라 아래와 같이 Between 시작값과 종료값을 바인딩
구분 | min | max | 이하 | 0 | 1000 |
---|---|---|---|---|---|
미만 | 0 | 999 | |||
이상 | 1000 | 999999999 | |||
초과 | 1001 | 999999999 |
연산자에 따라 바인딩 값 변경