정미나닷컴
[Oracle] 오라클 고급 JOIN 테크닉 - 상호배타적 관계의 JOIN 본문
상호배타적 관계의 JOIN
- 상호배타적 관계 : 어떤 엔티티가 두 개 이상의 다른 엔티티의 합집합과 관계를 갖는 것
- 상품권결제 테이블 모델링 방법
① 온라인권번호, 실권번호 두 컬럼을 따로 두고, 레코드별로 둘 중 하나의 컬럼에만 값을 입력
→ 외래키 분리
SELECT /*+ ordered use_nl(b) use_no(c) use_nl(d) */
A.주문번호, A.결제일자, A.결제금액,
NVL(B.온라인권번호, C.실권번호) 상품권번호,
NVL(B.발행일시, D.발행일시) 발행일시
FROM 상품권결제 A
LEFT OUTER JOIN 온라인권 B
ON B.온라인권번호 = A.온라인권번호
LEFT OUTER JOIN 실권 C
ON C.실권번호 = A.실권번호
LEFT OUTER JOIN 실권발행 D
ON D.발행번호 = C.발행번호
WHERE A.결제일자 BETWEEN :dt1 AND :dt2;
② 상품권구분과 상품권번호 컬럼을 두고, 상품권구분이 '1'일 때는 온라인권번호를 입력, '2'일 때는 실권번호를 입력
→ 외래키 통합
SELECT X.주문번호, X.결제일자, X.결제금액, Y.온라인권번호 상품권번호, Y.발행일시
FROM 상품권결제 X, 온라인권 Y
WHERE X.상품권구분 = '1'
AND X.결제일자 BETWEEN :dt1 AND :dt2
AND X.상품권번호 = Y.온라인권번호
UNION ALL
SELECT X.주문번호, X.결제일자, X.결제금액, Y.실권번호 상품권번호, Z.발행일시
FROM 상품권결제 X, 실권 Y, 실권발행 Z
WHERE X.상품권구분 = '2'
AND X.결제일자 BETWEEN :dt1 AND :dt2
AND X.상품권번호 = Y.실권번호
AND Y.발행번호 = Z.발행번호;
-- 인덱스가 【상품권구분 + 결제일자】 순이라면 비효율 없음
-- 인덱스가 【결제일자 + 상품권구분】 순이라면 인덱스 스캔범위 중복 발생
-- 인덱스가 【결제일자】 라면 상품권구분을 필터링하기 위한 테이블 random access까지 발생
▼
SELECT /*+ ordered use_nl(b) use_nl(c) use_no(d) */
A.주문번호, A.결제일자, A.결제금액,
NVL(B.온라인권번호, C.실권번호) 상품권번호,
NVL(B.발행일시, D.발행일시) 발행일시
FROM 상품권결제 A
LEFT OUTER JOIN 온라인권 B
ON B.온라인권번호 = DECODE(A.상품권구분,'1',A.상품권번호)
LEFT OUTER JOIN 실권 C
ON C.실권번호 = DECODE(A.상품권구분,'2',A.실권번호)
LEFT OUTER JOIN 실권발행 D
ON D.발행번호 = C.발행번호
WHERE A.결제일자 BETWEEN :dt1 AND :dt2;
-- DECODE를 없애도 결과는 같지만 JOIN 량이 두 배가 됨
'IT' 카테고리의 다른 글
[Oracle] 오라클 쿼리 변환 - 서브쿼리 Unnesting (0) | 2017.11.12 |
---|---|
[Oracle] 오라클 SQL 처리 절차 - CBO (Cost-Based Optimizer) (0) | 2017.11.11 |
[Oracle] 오라클 고급 JOIN 테크닉 - 징검다리 테이블 JOIN을 이용한 튜닝 (0) | 2017.11.08 |
[Oracle] 오라클 고급 JOIN 테크닉 - 선분이력 JOIN (0) | 2017.11.05 |
[Oracle] 오라클 고급 JOIN 테크닉 - 점이력 조회 (0) | 2017.11.05 |