( 기간조건이 있는 ) 날짜별데이터로 group by 한 집계데이터를 날짜컬럼으로 pivot 한후 다시 group by rollup 으로 합계 소계까지낸 집계데이터가있는데 결과 데이터(day1~day10)가 0인경우
grouping(gubun1) or grouping(gubun2) = 1, 0 인경우를 불문하고
last_value 함수로 0 이 아닌 값을 가져와야합니다
말로적으려니 참경우에 없고 성의도없는 질문같아서 죄송하네요..
실제로 제가 last_value로 해보니 데이터가 몇개없을때는
속도에 문제없지만 데이터개수가 늘어날수록 쿼리속도는 느려졌습니다
데이터가 0인경우 최근 이전날짜의 0이 아닌값을 가져와야하는데
속도가나오게 쿼리를 짤려면 어떻게해야할까요?
샘플이필요하시면 다시 만들어서 올릴께요...
기간조건이 day1(20170901) ~ day10(20170910) 이라면
gubun1 , gubun2, day1, day2, day3, ....., day 10
aa , bb, , 0 , 100, 0, 100, 10, 100, 0 , 0, 0, 10
이렇다면
예를들어서 day3 의값이 0이라면 day2의값 100이 last_value 값이됩니다..
day1의 값이 0이라면 day1(20170901) 보다 작은 0이아닌 최대의 날짜의 데이터를 가져와야합니다
만약 20170817 값이 1 이고 20170818~20170831 값이 전부 0 이라면 20170817의 1값이 last_value가 돼겠죠..
우리집아찌님이 말씀하신데로 테이블명 컬럼명만 바꿔서 올립니다
( 데이터및 결과화면이 필요하시면 다시 정리해서 올리겠습니다 )
0.아래의쿼리는 나름 LAST_VALUE를 써서 해본겁니다.
- WITH T1 까지가 1차적인 ROLLUP이고 밑의 T2 부터는 ROLLUP한데이터를 가공하기위한거니 신경안쓰셔도됩니다.
1. 기간조회는 2017-07-03 ~ 2017-07-30 을입력하면 화면달력에서 주차를
2017년 27주 ~ 2017년 30주로 검색이됩니다.
3개의 테이블입니다
TARGET_TABLE (메인테이블)
WEEK_T(입력날짜가 어느주에 속하는지 (년/월/주)로 가져오는 기준테이블)
LN_T( 라인테이블입니다)
--------------
TARGET_TABLE
--------------
F_CD
P_CD
YY
MM
WK
MD
LN
T_INI
T_TG
T_RS
BR
T_RT
RD
--------------
WEEK_T
--------------
YY
MM
WK
START_DT
END_DT
D_FLAG
U_FLAG
--------------
LN_T
--------------
LN_CD
LN_NM
요청하신쿼리는 아래와같습니다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | /* LAST_VALUE 이용한값처리 */ WITH T AS ( SELECT A.MD ,A.LN ,DECODE( B.IDX,1, 'GUBUN1' ,2, 'GUBUN2' ,3, 'GUBUN3' ,4, 'GUBUN4' ) GUBUN , SUM ( DECODE( A.YY||A.WK, '201727' , DECODE( B.IDX, 1, A.T_TG, 2, A.T_RS, 3, A.BR, 4, A.T_RT,0), 0 )) "201727" , SUM ( DECODE( A.YY||A.WK, '201728' , DECODE( B.IDX, 1, A.T_TG, 2, A.T_RS, 3, A.BR, 4, A.T_RT,0), 0 )) "201728" , SUM ( DECODE( A.YY||A.WK, '201729' , DECODE( B.IDX, 1, A.T_TG, 2, A.T_RS, 3, A.BR, 4, A.T_RT,0), 0 )) "201729" , SUM ( DECODE( A.YY||A.WK, '201730' , DECODE( B.IDX, 1, A.T_TG, 2, A.T_RS, 3, A.BR, 4, A.T_RT,0), 0 )) "201730" , SUM ( CASE WHEN A.YY||A.WK IN ( SELECT YY || LPAD(WK,2,0) FROM WEEK_T WHERE START_DT <= '20170730' AND END_DT >= '20170703' AND D_FLAG = 'N' AND U_FLAG = 'Y' AND D_FLAG = 'N' AND U_FLAG = 'Y' ) THEN DECODE(B.IDX,1,A.T_TG,2,A.T_RS,3,A.BR,4,A.T_RT,0) ELSE 0 END ) TOT ,B.IDX FROM ( SELECT NVL(A.MD,B.MD) MD ,NVL(A.LN,B.LN) LN ,NVL(A.YY,B.YY) YY ,NVL(A.MM,B.MM) MM ,NVL(A.WK,B.WK) WK ,NVL(TO_NUMBER(LAST_VALUE(DECODE(NVL(A.T_TG,B.T_TG),0, NULL ,NVL(A.T_TG,B.T_TG)) IGNORE NULLS) OVER (PARTITION BY A.F_CD,A.P_CD,A.MD,A.LN ORDER BY A.YY,A.MM,A.WK)),0) T_TG ,NVL(TO_NUMBER(LAST_VALUE(DECODE(NVL(A.T_RS,B.T_RS),0, NULL ,NVL(A.T_RS,B.T_RS)) IGNORE NULLS) OVER (PARTITION BY A.F_CD,A.P_CD,A.MD,A.LN ORDER BY A.YY,A.MM,A.WK)),0) T_RS ,NVL(TO_NUMBER(LAST_VALUE(DECODE(NVL(A.BR,B.BR),0, NULL ,NVL(A.BR,B.BR)) IGNORE NULLS) OVER (PARTITION BY A.F_CD,A.P_CD,A.MD,A.LN ORDER BY A.YY,A.MM,A.WK)),0) BR ,NVL(TO_NUMBER(LAST_VALUE(DECODE(NVL(A.T_RT,B.T_RT),0, NULL ,NVL(A.T_RT,B.T_RT)) IGNORE NULLS) OVER (PARTITION BY A.F_CD,A.P_CD,A.MD,A.LN ORDER BY A.YY,A.MM,A.WK)),0) T_RT -- ,NVL(A.T_TG,B.T_TG) T_TG -- ,NVL(A.T_RS,B.T_RS) T_RS -- ,NVL(A.BR,B.BR) BR -- ,NVL(A.T_RT,B.T_RT) T_RT FROM ( SELECT A.MD ,A.LN ,NVL(A.YY,B.YY) YY ,NVL(A.MM,B.MM) MM ,NVL(A.WK,B.WK) WK ,DENSE_RANK() OVER ( ORDER BY A.MD,A.LN) DR ,A.T_TG ,A.T_RS ,A.BR ,A.T_RT FROM ( SELECT YY YY ,LPAD(MM,2,0) MM ,LPAD(WK,2,0) WK FROM WK_T WHERE START_DT <= '20170730' AND END_DT >= '20170703' AND D_FLAG = 'N' AND U_FLAG = 'Y' ORDER BY YY, MM, WK ) B LEFT OUTER JOIN TARGET_TABLE A PARTITION BY (A.MD, A.LN ) ON ( A.YY = B.YY AND A.MM = B.MM AND A.WK = B.WK ) WHERE 1=1 AND A.LN <> '9999' ORDER BY A.MD ,A.LN ,NVL(A.YY,B.YY) ,NVL(A.MM,B.MM) ,NVL(A.WK,B.WK) ) A FULL OUTER JOIN ( SELECT * FROM TARGET_TABLE WHERE LN <> '9999' )B ON 1=1 AND A.MD = B.MD AND A.LN = B.LN AND A.YY = B.YY AND A.MM = B.MM AND A.WK = B.WK ORDER BY 1,2,3,4,5 )A ,( SELECT LEVEL IDX FROM DUAL CONNECT BY LEVEL <=4)B WHERE 1=1 GROUP BY A.MD ,A.LN ,B.IDX ORDER BY A.MD ,A.LN ,B.IDX ) /* 1차적인 rollup 값을 구한다 */ SELECT MD,LN,GUBUN , CASE WHEN "201727" = 0 AND GR>0 AND IDX = 2 THEN NULL ELSE "201727" END "201727" , CASE WHEN "201728" = 0 AND GR>0 AND IDX = 2 THEN NULL ELSE "201728" END "201728" , CASE WHEN "201729" = 0 AND GR>0 AND IDX = 2 THEN NULL ELSE "201729" END "201729" , CASE WHEN "201730" = 0 AND GR>0 AND IDX = 2 THEN NULL ELSE "201730" END "201730" , CASE WHEN TOT = 0 AND GR>0 AND IDX = 2 THEN NULL ELSE TOT END TOT ,GR,IDX,GR1 FROM ( SELECT DECODE(1, GROUPING (A.MD), 'Total' , A.MD) MD ,DECODE(1, GROUPING (A.MD), '' , GROUPING (A.LN), 'Sub Total' , A.LN) LN ,A.GUBUN , CASE WHEN MAX (A.IDX) IN (1,2) THEN ROUND( SUM ( "201727" ),1) WHEN MAX (A.IDX) IN (3,4) THEN ROUND( SUM ( "201727" ),0) ELSE 0 END "201727" , CASE WHEN MAX (A.IDX) IN (1,2) THEN ROUND( SUM ( "201728" ),1) WHEN MAX (A.IDX) IN (3,4) THEN ROUND( SUM ( "201728" ),0) ELSE 0 END "201728" , CASE WHEN MAX (A.IDX) IN (1,2) THEN ROUND( SUM ( "201729" ),1) WHEN MAX (A.IDX) IN (3,4) THEN ROUND( SUM ( "201729" ),0) ELSE 0 END "201729" , CASE WHEN MAX (A.IDX) IN (1,2) THEN ROUND( SUM ( "201730" ),1) WHEN MAX (A.IDX) IN (3,4) THEN ROUND( SUM ( "201730" ),0) ELSE 0 END "201730" , CASE WHEN MAX (A.IDX) IN (1,2) THEN ROUND( SUM (TOT),1) WHEN MAX (A.IDX) IN (3,4) THEN ROUND( SUM (TOT),0) ELSE 0 END TOT ,TO_CHAR(DENSE_RANK() OVER ( ORDER BY A.MD NULLS FIRST )-1) GR , MAX (A.IDX) IDX ,NVL(A.LN, '9999' ) GR1 FROM T A GROUP BY ROLLUP (A.MD, (A.LN)), GUBUN HAVING NOT ( MAX (A.IDX) IN (1,3,4) AND GROUPING (A.MD) = 0 AND GROUPING (A.LN) = 0 ) ORDER BY A.MD NULLS FIRST , A.LN NULLS FIRST , MAX (A.IDX) ) ; |
MD | LN | GUBUN | 201727 | 201728 | 201729 | 201730 | TOT | GR | IDX | GR1 |
Total | GUBUN1 | 1473.3 | 2120.1 | 2468.3 | 2822.3 | 8884.1 | 0 | 1 | 9999 | |
Total | GUBUN2 | 1789.8 | 2481.8 | 2899.7 | 3378.4 | 10549.6 | 0 | 2 | 9999 | |
Total | GUBUN3 | 30097 | 73566 | 94428 | 65274 | 263365 | 0 | 3 | 9999 | |
Total | GUBUN4 | -49017 | -138317 | -147006 | -252082 | -586422 | 0 | 4 | 9999 | |
MD1 | Sub Total | GUBUN1 | 12.2 | 24.3 | 24.3 | 24.3 | 85.1 | 1 | 1 | 9999 |
MD1 | Sub Total | GUBUN2 | 15.2 | 30.4 | 30.4 | 30.4 | 106.4 | 1 | 2 | 9999 |
MD1 | Sub Total | GUBUN3 | 0 | 0 | 0 | 0 | 0 | 1 | 3 | 9999 |
MD1 | Sub Total | GUBUN4 | 0 | -66 | -66 | -66 | -197 | 1 | 4 | 9999 |
MD1 | LN1 | GUBUN2 | 15.2 | 15.2 | 15.2 | 45.6 | 1 | 2 | LN1 | |
MD1 | LN2 | GUBUN2 | 15.2 | 15.2 | 15.2 | 15.2 | 60.8 | 1 | 2 | LN1 |
1 2 3 4 5 6 7 8 9 10 11 | MD LN GUBUN 201727 201728 201729 201730 TOT GR IDX GR1 Total GUBUN1 1473.3 2120.1 2468.3 2822.3 8884.1 0 1 9999 Total GUBUN2 1789.8 2481.8 2899.7 3378.4 10549.6 0 2 9999 Total GUBUN3 30097 73566 94428 65274 263365 0 3 9999 Total GUBUN4 -49017 -138317 -147006 -252082 -586422 0 4 9999 MD1 Sub Total GUBUN1 12.2 24.3 24.3 24.3 85.1 1 1 9999 MD1 Sub Total GUBUN2 15.2 30.4 30.4 30.4 106.4 1 2 9999 MD1 Sub Total GUBUN3 0 0 0 0 0 1 3 9999 MD1 Sub Total GUBUN4 0 -66 -66 -66 -197 1 4 9999 MD1 LN1 GUBUN2 15.2 15.2 15.2 45.6 1 2 LN1 MD1 LN2 GUBUN2 15.2 15.2 15.2 15.2 60.8 1 2 LN1 |
WITH T1 까지 결과를 일부 발췌한 결과입니다.
쿼리가 너무 길고 복잡하네요.
테이블도 몇개 안되고 사용되는 항목도 많지 않은데..이렇게까지 복잡할 이유가 없네요.
기간 조건 주는 방법도 너무 복잡하구요.
target_table 자료 좀 보여주세요. 표형태로.
전체 건수는 어느정도, 월별 건수는?
조회 기간 이전의 0 이 아닌 자료를 찾는 방법을 고민해야 합니다.
조회 기간보다 이전 자료를 더 가져와야지만 last_value 를 적용할 수 있겟지요?
0 인 자료가 연속되는 기간은 최대 어느 정도?
이 기간 정도만 더 가져오면 될지? 아니면 처음부터 다 가져와야 할지 등등..고민이 필요합니다.
TARGET 테이블입니다
TARGET 테이블데이터는 이미 주차별로 집계됀 테이블입니다 그래서 WEEK 단위입니다.
F_CD | P_CD | YY | MM | WK | MD | LN | T_TG | T_RS | BR | T_RT |
F01 | P01 | 2017 | 7 | 26 | M01 | L01 | 10.8 | 13.5 | 0 | |
F01 | P01 | 2017 | 7 | 31 | M02 | L02 | 13.44 | 16.8 | 0 | |
F01 | P01 | 2017 | 7 | 29 | M03 | L03 | 14.1375 | 14.5 | 0 | |
F01 | P01 | 2017 | 7 | 28 | M04 | L04 | 16.8 | 21 | 0 | |
F01 | P01 | 2017 | 7 | 31 | M05 | L05 | 11.2 | 14 | 0 | |
F01 | P01 | 2017 | 7 | 27 | M06 | L06 | 13.52 | 16.9 | 0 | -197.1666667 |
F01 | P01 | 2017 | 7 | 28 | M07 | L05 | 5.56 | 14 | 0 | |
F01 | P01 | 2017 | 7 | 27 | M01 | L01 | 10.8 | 13.5 | 0 | |
F01 | P01 | 2017 | 7 | 27 | M08 | L07 | 10 | 14 | 0 | |
F01 | P01 | 2017 | 7 | 29 | M09 | L08 | 11.2 | 14 | 0 | |
F01 | P01 | 2017 | 7 | 30 | M10 | L09 | 13.775 | 14.5 | 0 | |
F01 | P01 | 2017 | 7 | 28 | M11 | L10 | 11.36 | 15 | 0 | |
F01 | P01 | 2017 | 7 | 29 | M12 | L11 | 8.24 | 10.3 | 0 | |
F01 | P01 | 2017 | 7 | 30 | M13 | L12 | 10.384 | 15 | 0 | |
F01 | P01 | 2017 | 7 | 27 | M14 | L13 | 5.384 | 14 | 0 | |
F01 | P01 | 2017 | 7 | 30 | M03 | L14 | 13.775 | 14.5 | 0 | |
F01 | P01 | 2017 | 7 | 27 | M15 | L15 | 14 | 17.5 | 0 | |
F01 | P01 | 2017 | 7 | 29 | M16 | L16 | 14.5 | 14.5 | 0 | |
F01 | P01 | 2017 | 7 | 31 | M11 | L17 | 11.36 | 14.2 | 0 | |
F01 | P01 | 2017 | 7 | 30 | M17 | L12 | 12 | 15.99 | -31.5975 | -127.3475 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | with t (f_cd, p_cd, yy, mm, wk, md, ln, t_tg, t_rs, br, t_rt ) as ( select 'F01' , 'P01' , '2017' , '7' , '26' , 'M01' , 'L01' ,10.8,13.5,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '31' , 'M02' , 'L02' ,13.44,16.8,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '29' , 'M03' , 'L03' ,14.1375,14.5,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '28' , 'M04' , 'L04' ,16.8,21,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '31' , 'M05' , 'L05' ,11.2,14,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '27' , 'M06' , 'L06' ,13.52,16.9,0,-197.1666667 from dual union all select 'F01' , 'P01' , '2017' , '7' , '28' , 'M07' , 'L05' ,5.56,14,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '27' , 'M01' , 'L01' ,10.8,13.5,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '27' , 'M08' , 'L07' ,10,14,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '29' , 'M09' , 'L08' ,11.2,14,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '30' , 'M10' , 'L09' ,13.775,14.5,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '28' , 'M11' , 'L10' ,11.36,15,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '29' , 'M12' , 'L11' ,8.24,10.3,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '30' , 'M13' , 'L12' ,10.384,15,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '27' , 'M14' , 'L13' ,5.384,14,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '30' , 'M03' , 'L14' ,13.775,14.5,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '27' , 'M15' , 'L15' ,14,17.5,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '29' , 'M16' , 'L16' ,14.5,14.5,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '31' , 'M11' , 'L17' ,11.36,14.2,0,0 from dual union all select 'F01' , 'P01' , '2017' , '7' , '30' , 'M17' , 'L12' ,12,15.99,-31.5975,0 from dual ) select t.* from t |
1 2 3 4 5 6 7 8 9 10 11 12 13 | -- 0) 7/03 ------------- 7/30 -- 조회기준 -- 1) s -------------- e -- 검색대상 -- 2) s --- e -- 검색대상 -- 3) s ----------------- e -- 검색대상 -- 4) s -------------------------------------- e -- 검색대상 -- 5) s --- e -- 제외대상 -- 6) s --- e -- 제외대상 -- 0) 을 기준으로 검색 대상인 1),2),3),4) 는 모두 -- s 가 7/30 보다 작고. AND start_dt <= '20170730' -- e 가 7/03 보다 크죠. AND end_dt >= '20170703' -- 이 두가지 조건으로 검색 대상인 1),2),3),4) 가 모두 검출됩니다. -- 제외 대상이 5), 6) 은 제외되구요. |