GROUP_NO | PK_DATE | PK_SEQ | AMOUNT |
3015 |
20180907 | 3 | 3000 |
2003 | 20180906 | 2 | 2000 |
1005 | 20180909 | 7 | 4000 |
1005 | 20180907 | 9 | 3000 |
2003 | 20180907 | 1 | 1000 |
1005 | 20180909 | 6 | 3000 |
3015 | 20180907 | 4 | 4000 |
1005 | 20180908 | 33 | 1500 |
3015 | 20180905 | 27 | 200 |
실제 테이블에는 위와 같은 데이터가 2600만건 정도 있고, GROUP_NO도 제가 위에 적어놓은 3015,2003,1005 이외에도 수십개가 더 있긴 합니다. 제가 인터넷 되는 컴퓨터로 데이터를 옮기기가 너무 힘들어 수기로 적다보니... 많이 빠지긴 했습니다...
컬럼도 몇개 더 있는데 뽑을 데이터가 저거면 충분할거 같아 생략했습니다. ㅠ.ㅠ
PK는 GROUP_NO, PK_DATE, PK_SEQ 세개입니다!
여기서 뽑아야될 데이터가 오늘(당일) 날짜 이전의 데이터 중에 가장 최신 데이터를 GROUP_NO당 하나 뽑는건데요.
SEQ는 높을수록 최신이고 DATE는 오늘에 가까울수록 최근이구요.
그래서 제가 짜본 쿼리가
SELECT *
FROM (
SELECT GROUP_NO
, PK_DATE
, PK_SEQ
, AMOUNT
, RANK() OVER(PARTITION BY GROUP_NO ORDER BY PK_DATE DESC, PK_SEQ DESC) RK
FROM T
WHERE PK_DATE < TO_DATE('20180910', 'YYYYMMDD')
AND GROUP_NO IN ('3015','2003','1005')
)
WHERE RK = 1
요렇게 뽑으니 나오긴 하는데... 테이블의 데이터가 이상하게 들어 있는지 1분이 넘게 걸리는 불상사가...=_=a
혹시 좀 나은 방법이 있을까 해서요....ㅠㅠ
1. pk_date 컬럼의 자료형 확인하세요.
- date 인지? varchar2 인지?
- varchar2 라면 조건 잘못 준 듯 하고요
2. 실행계획 확인해 보세요.
- inlist iterator 로 처리 범위를 줄여야 하고요.
- window sort pushed rank 로 정렬을 효율적으로 해야 합니다.
- index_desc 힌트를 통해 window nosort 를 유도해 보세요.
- nosort 가 pushed rank 보다 효율적입니다.
- 어차피 PK 라서 rank 를 써도 결과는 같지만. row_number 가 의미상 맞습니다.