front 작업만 해서 쿼리 만질일이 없다가 오랜만에 다시 쿼리를 해본다.
통계데이터를 만드는 일인데, 확실히 쿼리로 처리하면 java로 처리하는것 보다 편하다.
1 2 3 4 5 6 7 8 9 | with data as ( select '2016-06-11' dt, 'typeA' type, 'itemA' item, '10000' amount from dual union all select '2016-06-11' dt, 'typeA' type, 'itemB' item, '20000' amount from dual union all select '2016-06-11' dt, 'typeB' type, 'itemB' item, '20000' amount from dual union all select '2016-06-11' dt, 'typeB' type, 'itemD' item, '20000' amount from dual union all select '2016-06-12' dt, 'typeC' type, 'itemC' item, '15000' amount from dual union all select '2016-06-13' dt, 'typeC' type, 'itemA' item, '30000' amount from dual ) select * from data; | cs |
위와 같이 데이터가 있을 대 날짜를 열로 하고 Type,Item별로 합계를 내는 통계라고 할때, oracle pivot함수를 이용하면 조회를
하면 아래와 같은 결과물이 나온다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | with data as ( select '2016-06-11' dt, 'typeA' type, 'itemA' item, '10000' amount from dual union all select '2016-06-11' dt, 'typeA' type, 'itemB' item, '20000' amount from dual union all select '2016-06-11' dt, 'typeB' type, 'itemB' item, '20000' amount from dual union all select '2016-06-11' dt, 'typeB' type, 'itemD' item, '20000' amount from dual union all select '2016-06-12' dt, 'typeC' type, 'itemC' item, '15000' amount from dual union all select '2016-06-13' dt, 'typeC' type, 'itemA' item, '30000' amount from dual ) select * from data PIVOT ( SUM(AMOUNT) FOR DT IN ('2016-06-11','2016-06-12','2016-06-13') ); | cs |
여기서 Type과 Item별로 합산 통계를 중간에 넣으려면 rollup 함수를 이용하면 간단히 해결가능하다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | with data as ( select '2016-06-11' dt, 'typeA' type, 'itemA' item, '10000' amount from dual union all select '2016-06-11' dt, 'typeA' type, 'itemB' item, '20000' amount from dual union all select '2016-06-11' dt, 'typeB' type, 'itemB' item, '20000' amount from dual union all select '2016-06-11' dt, 'typeB' type, 'itemD' item, '20000' amount from dual union all select '2016-06-12' dt, 'typeC' type, 'itemC' item, '15000' amount from dual union all select '2016-06-13' dt, 'typeC' type, 'itemA' item, '30000' amount from dual ) select type, item, sum(d1) as "2016-06-11", sum(d2) as "2016-06-12", sum(d3) as "2016-06-13" from ( select * from data PIVOT ( SUM(AMOUNT) FOR DT IN ('2016-06-11' as d1,'2016-06-12' as d2,'2016-06-13' as d3) ) ) group by rollup(type,item) | cs |
위와같이 노란색으로 표시한 부분이 type별 합산과 토탈 합산이다.
그런데 이런 합계를 위로 보여주고 싶을 경우에는 아래와 같이 grouping을 통해 순서를 변경해 준다.
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 | with data as ( select '2016-06-11' dt, 'typeA' type, 'itemA' item, '10000' amount from dual union all select '2016-06-11' dt, 'typeA' type, 'itemB' item, '20000' amount from dual union all select '2016-06-11' dt, 'typeB' type, 'itemB' item, '20000' amount from dual union all select '2016-06-11' dt, 'typeB' type, 'itemD' item, '20000' amount from dual union all select '2016-06-12' dt, 'typeC' type, 'itemC' item, '15000' amount from dual union all select '2016-06-13' dt, 'typeC' type, 'itemA' item, '30000' amount from dual ) select type, item, sum(d1) as "2016-06-11", sum(d2) as "2016-06-12", sum(d3) as "2016-06-13" from ( select * from data PIVOT ( SUM(AMOUNT) FOR DT IN ('2016-06-11' as d1,'2016-06-12' as d2,'2016-06-13' as d3) ) ) group by rollup(type,item) order by grouping(type) desc, type, grouping(item) desc, item | cs |
근데 사실 동일한 기능이지만 decode로 처리하게 되면 아래와 같이 쿼리가 훨씬 간결해 진다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | with data as ( select '2016-06-11' dt, 'typeA' type, 'itemA' item, '10000' amount from dual union all select '2016-06-11' dt, 'typeA' type, 'itemB' item, '20000' amount from dual union all select '2016-06-11' dt, 'typeB' type, 'itemB' item, '20000' amount from dual union all select '2016-06-11' dt, 'typeB' type, 'itemD' item, '20000' amount from dual union all select '2016-06-12' dt, 'typeC' type, 'itemC' item, '15000' amount from dual union all select '2016-06-13' dt, 'typeC' type, 'itemA' item, '30000' amount from dual ) select type, item, sum(decode(dt,'2016-06-11',amount)) as "2016-06-11", sum(decode(dt,'2016-06-12',amount)) as "2016-06-12", sum(decode(dt,'2016-06-13',amount)) as "2016-06-13" from data group by rollup(type,item) order by grouping(type) desc, type, grouping(item) desc, item; | cs |
결과는 동일하다.
PIVOT에 경우 Java iBatis에서 컬럼을 dynamic하게 만들경우 동작하지 않는다.
decode가 깔끔하고 좋은듯 하다. 물론 성능 이슈는 확인하지 않았다. 실행계획상 cost는 거의 동일..
물론 데이터가 워낙에 작으니.^^
알아두변 유용한 decode로 열행 바꾸기 + rollup으로 부분합산 구하기 였다.