WITH t_in AS (-- 입고 SELECT 'a' co, '20120701' dt, 100 amt FROM dual UNION ALL SELECT 'a', '20120715', 100 FROM dual UNION ALL SELECT 'b', '20120703', 100 FROM dual UNION ALL SELECT 'b', '20120710', 100 FROM dual UNION ALL SELECT 'c', '20120702', 100 FROM dual UNION ALL SELECT 'c', '20120709', 100 FROM dual ) , t_out AS (-- 출고 SELECT 'a' co, '20120702' dt, 10 amt FROM dual UNION ALL SELECT 'a', '20120705', 30 FROM dual UNION ALL SELECT 'a', '20120705', 50 FROM dual ) , t_bas AS (-- 이월 SELECT 'c' co, '20120701' dt, 40 amt FROM dual ) , t_cal AS (-- 달력 SELECT TO_CHAR(TO_DATE('201207', 'yyyymm') + LEVEL - 1, 'yyyymmdd') dt FROM dual CONNECT BY LEVEL <= 31 ) SELECT b.co 회사 , a.dt 일자 , NVL(amt_bas, 0) 이월 , NVL(amt_in , 0) 입고 , NVL(amt_out, 0) 출고 , SUM(NVL(amt_bas, 0) + NVL(amt_in , 0) - NVL(amt_out, 0)) OVER(PARTITION BY b.co ORDER BY a.dt) 재고 FROM t_cal a LEFT OUTER JOIN ( SELECT co, dt , SUM(amt_bas) amt_bas , SUM(amt_in ) amt_in , SUM(amt_out) amt_out FROM ( SELECT co, dt, amt amt_bas, 0 amt_in, 0 amt_out FROM t_bas UNION ALL SELECT co, dt, 0 amt_bas, amt amt_in, 0 amt_out FROM t_in UNION ALL SELECT co, dt, 0 amt_bas, 0 amt_in, amt amt_out FROM t_out ) WHERE dt LIKE '201207'||'%' GROUP BY co, dt ) b PARTITION BY (b.co) ON a.dt = b.dt WHERE a.dt LIKE '201207'||'%' ;
-- 음.. Partition Outer Join 은 10g 의 새 기능입니다. -- 9i 라면 쿼리가 좀더 복잡합니다. WITH t_in AS (-- 입고 SELECT 'a' co, '20120701' dt, 100 amt FROM dual UNION ALL SELECT 'a', '20120715', 100 FROM dual UNION ALL SELECT 'b', '20120703', 100 FROM dual UNION ALL SELECT 'b', '20120710', 100 FROM dual UNION ALL SELECT 'c', '20120702', 100 FROM dual UNION ALL SELECT 'c', '20120709', 100 FROM dual ) , t_out AS (-- 출고 SELECT 'a' co, '20120702' dt, 10 amt FROM dual UNION ALL SELECT 'a', '20120705', 30 FROM dual UNION ALL SELECT 'a', '20120705', 50 FROM dual ) , t_bas AS (-- 이월 SELECT 'c' co, '20120701' dt, 40 amt FROM dual ) , t_cal AS (-- 달력 SELECT TO_CHAR(TO_DATE('201207', 'yyyymm') + LEVEL - 1, 'yyyymmdd') dt FROM dual CONNECT BY LEVEL <= 31 ) , tmp_mst AS ( SELECT co, dt , SUM(amt_bas) amt_bas , SUM(amt_in ) amt_in , SUM(amt_out) amt_out FROM ( SELECT co, dt, amt amt_bas, 0 amt_in, 0 amt_out FROM t_bas UNION ALL SELECT co, dt, 0 amt_bas, amt amt_in, 0 amt_out FROM t_in UNION ALL SELECT co, dt, 0 amt_bas, 0 amt_in, amt amt_out FROM t_out ) WHERE dt LIKE '201207'||'%' GROUP BY co, dt ) , tmp_cal AS ( SELECT co, dt FROM (SELECT DISTINCT co FROM tmp_mst) , (SELECT dt FROM t_cal WHERE dt LIKE '201207'||'%') ) SELECT a.co 회사 , a.dt 일자 , NVL(amt_bas, 0) 이월 , NVL(amt_in , 0) 입고 , NVL(amt_out, 0) 출고 , SUM(NVL(amt_bas, 0) + NVL(amt_in , 0) - NVL(amt_out, 0)) OVER(PARTITION BY a.co ORDER BY a.dt) 재고 FROM tmp_cal a , tmp_mst b WHERE a.co = b.co(+) AND a.dt = b.dt(+) ;