トップページに戻る    次のSQLパズルへ    前のSQLパズルへ

3-17 case式とignore nullsその2

SQLパズル

収支テーブル
      日付  収入  支出
----------  ----  ----
2005/12/10     3     1
2005/12/11     5     2
2005/12/12     4     9
2005/12/13     5     2
2005/12/14     9     1
2005/12/15     6     3
2005/12/16     1     5
2005/12/17     0     6
2005/12/18     3     1

収支テーブルから、
日付、収入、支出、
収支(収入-支出)と、過去で直近の黒字の日の収支、過去で直近の黒字の日
を求める。

出力結果
      日付  収入   支出  収支  直近の黒字収支   直近の黒字日
----------  ----  ----  ----  --------------  ------------
2005/12/10     3     1     2               2   2005/12/10
2005/12/11     5     2     3               3   2005/12/11
2005/12/12     4     9    -5               3   2005/12/11
2005/12/13     5     2     3               3   2005/12/13
2005/12/14     9     1     8               8   2005/12/14
2005/12/15     6     3     3               3   2005/12/15
2005/12/16     1     5    -4               3   2005/12/15
2005/12/17     0     6    -6               3   2005/12/15
2005/12/18     3     1     2               2   2005/12/18


データ作成スクリプト

create table 収支(
日付 date,
収入 number(1),
支出 number(1));

insert into 収支 values(to_date('20051210','YYYYMMDD'),3,1);
insert into 収支 values(to_date('20051211','YYYYMMDD'),5,2);
insert into 収支 values(to_date('20051212','YYYYMMDD'),4,9);
insert into 収支 values(to_date('20051213','YYYYMMDD'),5,2);
insert into 収支 values(to_date('20051214','YYYYMMDD'),9,1);
insert into 収支 values(to_date('20051215','YYYYMMDD'),6,3);
insert into 収支 values(to_date('20051216','YYYYMMDD'),1,5);
insert into 収支 values(to_date('20051217','YYYYMMDD'),0,6);
insert into 収支 values(to_date('20051218','YYYYMMDD'),3,1);
commit;


SQL

col 収入 for 9999
col 支出 for 9999
col 収支 for 9999

--■■■case式とignore nullsを使う方法(10g以降)■■■
select to_char(日付,'YYYY/MM/DD') as 日付,収入,支出,
収入-支出 as 収支,
Last_Value(case when 収入-支出 >= 0
           then 収入-支出 end ignore nulls) over(order by 日付) as 直近の黒字収支,
to_char(Last_Value(case when 収入-支出 >= 0
                   then 日付 end ignore nulls) over(order by 日付),'YYYY/MM/DD') as 直近の黒字日
from 収支;

--■■■自己結合を使う方法■■■
select to_char(a.日付,'YYYY/MM/DD') as 日付,a.収入,a.支出,
a.収入-a.支出 as 収支,
b.収入-b.支出 as 直近の黒字収支,
to_char(b.日付,'YYYY/MM/DD') as 直近の黒字日
from 収支 a,収支 b
where b.日付 = (select max(c.日付) from 収支 c
                 where c.日付 <= a.日付
                   and c.収入-c.支出 >=0);


解説

Oracle10g以降なら、
case式とignore nullsを組み合わせる方法があります。

分析関数の衝撃6 (応用編)