피봇 쿼리 질문드립니다 0 3 2,240

by 김용한 [2015.03.20 19:21:23]


YR 01 02 03 04 05 06 07 08 09 10 11 12
1012         1              
2011                       385
2012 890 645 833 416 739 360 552 828 297 223 348 228
2013 1332 680 841 385 327 781 459 829 207 135 190 466
2014 261 432 895 347 396 471 529 495 159 173 167 356
2015 439 266 361                  

위의테이블을

아래의 테이블로 변환하고싶어요

1012 01  
  02  
  03  
  04  
  05 1
  06  
  07  
  08  
  09  
  10  
  11  
  12  
2011 01  
  02  
  03  
  04  
  05  
  06  
  07  
  08  
  09  
  10  
  11  
  12 385

 

select a.issu_yyyy as yr
     , sum(max(decode(a.issu_mm,'01',a.cnt))) over (partition by a.issu_yyyy)  as "01"
     , sum(max(decode(a.issu_mm,'02',a.cnt))) over (partition by a.issu_yyyy)  as "02"
     , sum(max(decode(a.issu_mm,'03',a.cnt))) over (partition by a.issu_yyyy)  as "03"
     , sum(max(decode(a.issu_mm,'04',a.cnt))) over (partition by a.issu_yyyy)  as "04"
     , sum(max(decode(a.issu_mm,'05',a.cnt))) over (partition by a.issu_yyyy)  as "05"
     , sum(max(decode(a.issu_mm,'06',a.cnt))) over (partition by a.issu_yyyy)  as "06"
     , sum(max(decode(a.issu_mm,'07',a.cnt))) over (partition by a.issu_yyyy)  as "07"
     , sum(max(decode(a.issu_mm,'08',a.cnt))) over (partition by a.issu_yyyy)  as "08"
     , sum(max(decode(a.issu_mm,'09',a.cnt))) over (partition by a.issu_yyyy)  as "09"
     , sum(max(decode(a.issu_mm,'10',a.cnt))) over (partition by a.issu_yyyy)  as "10"
     , sum(max(decode(a.issu_mm,'11',a.cnt))) over (partition by a.issu_yyyy)  as "11"
     , sum(max(decode(a.issu_mm,'12',a.cnt))) over (partition by a.issu_yyyy)  as "12"
from
(select to_char(a.issu_dt,'yyyy') as issu_yyyy
         , to_char(a.issu_dt,'mm') as issu_mm
         , sum(a.seal_use_nocopy) as cnt
      from ADM.gnaf201 a
     where 1=1 
       and a.doc_knd_gbn = '1'  -- 문서
  group by to_char(a.issu_dt,'yyyy')
         , to_char(a.issu_dt,'mm')
  )a,(select level || '월' as mm, to_char(level,'00') as val from dual
    connect by level <= 12) b
--where a.issu_yyyy='1012'    
group by a.issu_yyyy
order by a.issu_yyyy

위의 테이블쿼리는 이상과같습니다..

by 김용한 [2015.03.21 10:24:44]

마농님의 예전 http://www.gurubee.net/article/55463 댓글을 보고 이해가더군요 ㅠㅠ

WITH T AS (
select 1012 as YR, 0 as "01", 0 as "02", 0 as "03", 0 as "04", 0 as "05", 0 as "06", 0 as "07", 0 as "08", 0 as "09", 0 as "10", 0 as "11", 0 as "12" from dual union all
select 2011 as YR, 0 as "01", 0 as "02", 0 as "03", 0 as "04", 0 as "05", 0 as "06", 0 as "07", 0 as "08", 0 as "09", 0 as "10", 0 as "11", 385 as "12" from dual union all
select 2012 as YR, 890 as "01", 645 as "02", 833 as "03", 416 as "04", 739 as "05", 360 as "06", 552 as "07", 828 as "08", 297 as "09", 223 as "10", 348 as "11", 228 as "12" from dual union all
select 2013 as YR, 1332 as "01", 680 as "02", 841 as "03", 385 as "04", 327 as "05", 781 as "06", 459 as "07", 829 as "08", 207 as "09", 135 as "10", 190 as "11", 466 as "12" from dual union all
select 2014 as YR, 261 as "01", 432 as "02", 895 as "03", 347 as "04", 396 as "05", 471 as "06", 529 as "07", 495 as "08", 159 as "09", 173 as "10", 167 as "11", 356 as "12" from dual union all
select 2015 as YR, 439 as "01", 266 as "02", 361 as "03", 0 as "04", 0 as "05", 0 as "06", 0 as "07", 0 as "08", 0 as "09", 0 as "10", 0 as "11", 0 as "12" from dual
)
select yr
     , lv as mm
     , decode(lv,1, "01"
                ,2, "02"
                ,3, "03"
                ,4, "04"
                ,5, "05"
                ,6, "06"
                ,7, "07"
                ,8, "08"
                ,9, "09"
                ,10,"10"
                ,11,"11"
                ,12,"12"
                ,0) as VAL
  from (select level lv from dual connect by level<=12),t 
 --where t.yr='2012'
 order by yr,mm


by 마농 [2015.03.22 13:13:00]

글쎄요...
1. 원본 쿼리도 문제점(불필요한 부분)이 많이 있구요.
  - b 집합이 쓸데 없이 조인되었구요
  - 이 때문인지? Over 분석함수 구문도 쓸데 없이 사용되었습니다.
 

SELECT TO_CHAR(issu_dt, 'yyyy') AS yr
     , SUM(DECODE(TO_CHAR(issu_dt, 'mm'), '01', seal_use_nocopy)) AS "01"
     , SUM(DECODE(TO_CHAR(issu_dt, 'mm'), '02', seal_use_nocopy)) AS "02"
     , SUM(DECODE(TO_CHAR(issu_dt, 'mm'), '03', seal_use_nocopy)) AS "03"
     , SUM(DECODE(TO_CHAR(issu_dt, 'mm'), '04', seal_use_nocopy)) AS "04"
     , SUM(DECODE(TO_CHAR(issu_dt, 'mm'), '05', seal_use_nocopy)) AS "05"
     , SUM(DECODE(TO_CHAR(issu_dt, 'mm'), '06', seal_use_nocopy)) AS "06"
     , SUM(DECODE(TO_CHAR(issu_dt, 'mm'), '07', seal_use_nocopy)) AS "07"
     , SUM(DECODE(TO_CHAR(issu_dt, 'mm'), '08', seal_use_nocopy)) AS "08"
     , SUM(DECODE(TO_CHAR(issu_dt, 'mm'), '09', seal_use_nocopy)) AS "09"
     , SUM(DECODE(TO_CHAR(issu_dt, 'mm'), '10', seal_use_nocopy)) AS "10"
     , SUM(DECODE(TO_CHAR(issu_dt, 'mm'), '11', seal_use_nocopy)) AS "11"
     , SUM(DECODE(TO_CHAR(issu_dt, 'mm'), '12', seal_use_nocopy)) AS "12"
  FROM adm.gnaf201
 WHERE doc_knd_gbn = '1'
 GROUP BY TO_CHAR(issu_dt, 'yyyy')
 ORDER BY yr
;

2. 원본 쿼리를 이용해 다시 2차 결과를 구하는 것도 문제입니다.
  - 1차 가공 집합을 다시 원본으로 해서 2차 가공하는 형태인데요.
  - 1차 가공이 과연 마지막 결과를 위해 꼭 필요한 과정인가 고민해볼 필요가 있습니다.
  - 없는 월도 나오게 하려면 아우터 조인을 이용하면 되구요.
  - 단, 이 경우엔 년도 조건이 필수로 추가되어야 하므로 파티션 아우터 조인이 필요합니다.
 

SELECT b.yr
     , a.mm
     , b.cnt
  FROM (SELECT LEVEL mm FROM dual CONNECT BY LEVEL <= 12) a
  LEFT OUTER JOIN
       (SELECT TO_CHAR(issu_dt, 'yyyy') AS yr
             , TO_CHAR(issu_dt, 'mm'  ) AS mm
             , SUM(seal_use_nocopy)     AS cnt
         WHERE doc_knd_gbn = '1'
         GROUP BY TO_CHAR(issu_dt, 'yyyy')
                , TO_CHAR(issu_dt, 'mm'  )
        ) b
 PARTITION BY (b.yr)
    ON a.mm = b.mm
 ORDER BY yr, mm
;

 


by 김용한 [2015.03.23 01:01:59]

마지막쿼리처럼 저렇게쉽게돼는군요 

원본 쿼리에서 1차 2차도출하는형태로 주로해와서 ...

많이 배우고 갑니다 감사드려요

 

 with t as (
  select to_date('20140501','yyyymmdd') as issu_dt, 20 as seal_use_nocopy from dual union all
  select to_date('20140601','yyyymmdd') as issu_dt, 30 as seal_use_nocopy from dual union all
  select to_date('20140701','yyyymmdd') as issu_dt, 40 as seal_use_nocopy from dual union all
  select to_date('20140801','yyyymmdd') as issu_dt, 50 as seal_use_nocopy from dual
 )
 SELECT b.yr
     , a.mm
     , b.cnt
  FROM (SELECT LEVEL mm FROM dual CONNECT BY LEVEL <= 12) a
  LEFT OUTER JOIN
       (SELECT TO_CHAR(issu_dt, 'yyyy') AS yr
       , TO_CHAR(issu_dt, 'mm'  ) AS mm
       , SUM(seal_use_nocopy)     AS cnt
       from t
   WHERE 1=1
     --and doc_knd_gbn = '1'
   GROUP BY TO_CHAR(issu_dt, 'yyyy')
          , TO_CHAR(issu_dt, 'mm'  )
  ) b
 PARTITION BY (b.yr)
    ON a.mm = b.mm
 ORDER BY yr, mm
;

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입