create table LPO(ID,dayC,Val) as
select 'あ',date '2010-03-01', 100 from dual union all
select 'あ',date '2010-04-01', 200 from dual union all
select 'あ',date '2010-06-01', 600 from dual union all
select 'あ',date '2010-07-01',3000 from dual union all
select 'い',date '2010-04-01', 200 from dual union all
select 'い',date '2010-06-01', 300 from dual union all
select 'い',date '2010-07-01', 900 from dual union all
select 'う',date '2010-04-01', 700 from dual union all
select 'う',date '2010-05-01',2000 from dual;
--■■■Partitioned Outer Joinを使う方法(10g以降)■■■
select c.ID,add_months(a.minV,b.cnter) as dayC,
nvl(c.val,0) as val,sum(nvl(c.val,0)) over(partition by c.ID order by b.cnter) as rumSum
from (select min(dayC) as minV,max(dayC) as maxV from LPO) a
Join
(select RowNum-1 as cnter from dict) b
on add_months(a.minV,b.cnter) <= a.maxV
Left Join LPO c partition by(c.ID)
on add_months(a.minV,b.cnter) = c.dayC
order by ID,dayC;
--■■■再帰with句を使う方法(11gR2以降)■■■
with rec(ID,currV,maxV,Val,rumSum,willOut) as(
select distinct ID,
cast(add_months(min(dayC) over(),-1) as date),
cast(max(DayC) over() as date),0,0,0
from LPO
union all
select a.ID,
cast(add_months(a.currV,1) as date),
cast(a.maxV as date),
nvl(b.Val,0),a.rumSum+nvl(b.Val,0),1
from rec a Left Join LPO b
on add_months(a.currV,1) = b.dayC
and a.ID=b.ID
where a.currV < a.maxV)
select ID,currV,Val,rumSum from rec where willOut=1
order by ID,currV;
--■■■Partitioned Outer Joinを使わない方法■■■
select a.ID,add_months(b.minV,c.cnter) as dayC,
nvl(d.val,0) as val,
sum(nvl(d.val,0)) over(partition by a.ID order by c.cnter) as rumSum
from (select distinct ID from LPO) a
cross Join (select min(dayC) as minV,max(dayC) as maxV from LPO) b
Join (select RowNum-1 as cnter from dict) c
on add_months(b.minV,c.cnter) <= b.maxV
Left Join LPO d
on a.ID = d.ID
and add_months(b.minV,c.cnter) = d.DAYC;