Skip to content
튜닝 연습서브쿼리와 쿼리 변환
SUBQ-038

「발주 누락 점검」에 6월에 발주한 상품까지 109개가 다 나온다

중급SELECT유통273 / 700

상황 ​

구매팀의 「발주 누락 점검」은 달마다 상품 109개 가운데 그달 발주가 한 번도 없는 상품을 뽑는다. 발주 담당이 빠뜨린 품목을 찾으려는 화면이다. 2023년 6월 점검표에 109개가 전부 나왔고, 그중에는 6월 12일에 발주한 원두와 우유도 있었다. 조민우는 "외부 조인으로 붙여서 짝이 없는 것만 IS NULL로 골랐다. 발주 헤더에만 6월 조건을 걸었으니 맞을 텐데"라고 한다.

테이블과 인덱스 ​

  • CF01 상품: 109행 · 5블록 · CF01_PK (ITM_NO) · 거래처 상품 68개 + 매장 제조 상품 41개(발주한 적이 없다)
  • CF12 발주: 734행 · 10블록 · CF12_PK (ORD_NO) · ORD_DT VARCHAR2(8) · 2023년 6월 28건
  • CF13 발주상품: 7,102행 · 57블록 · CF13_PK (ORD_NO, ITM_NO) · 2023년 6월 271줄(상품 68개) · 거래처 상품 68개는 다른 달에도 거의 매달 발주된다
  • 통계 최신

원본 SQL ​

sql
SELECT DISTINCT p.ITM_NO, p.ITM_NM
  FROM CF01 p, CF13 d, CF12 h
 WHERE d.ITM_NO(+) = p.ITM_NO
   AND h.ORD_NO(+) = d.ORD_NO
   AND h.ORD_DT(+) BETWEEN '20230601' AND '20230630'
   AND h.ORD_NO IS NULL
 ORDER BY p.ITM_NO

실행계획 학습용 예시 · 건수는 적재 데이터 그대로 ​

xplan
------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |      |      1 |        |    109 |00:00:00.01 |      72 |          |
|   1 |  SORT UNIQUE            |      |      1 |    109 |    109 |00:00:00.01 |      72 | 9216  (0)|
|*  2 |   FILTER                |      |      1 |        |   6872 |00:00:00.01 |      72 |          |
|*  3 |    HASH JOIN RIGHT OUTER|      |      1 |   7143 |   7143 |00:00:00.01 |      72 | 1269K (0)|
|*  4 |     TABLE ACCESS FULL   | CF12 |      1 |     28 |     28 |00:00:00.01 |      10 |          |
|*  5 |     HASH JOIN OUTER     |      |      1 |   7143 |   7143 |00:00:00.01 |      62 | 1180K (0)|
|   6 |      TABLE ACCESS FULL  | CF01 |      1 |    109 |    109 |00:00:00.01 |       5 |          |
|   7 |      TABLE ACCESS FULL  | CF13 |      1 |   7102 |   7102 |00:00:00.01 |      57 |          |
------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("H"."ORD_NO" IS NULL)
   3 - access("H"."ORD_NO"(+)="D"."ORD_NO")
   4 - filter(("H"."ORD_DT">='20230601' AND "H"."ORD_DT"<='20230630'))
   5 - access("D"."ITM_NO"(+)="P"."ITM_NO")

문제 ​

  1. 6월에 발주한 상품까지 109개가 모두 나온 까닭을 실행계획 2 ~ 5번 줄의 A-Rows로 설명하시오. DISTINCT가 무엇을 가렸는지도 쓰시오.
  2. 상품마다 '6월 발주가 있는가'를 판정하도록 SQL을 고치시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자