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

9-55 ランを求める

SQLパズル

株価推移テーブル
      年月  株価
----------  ----
2007/01/06  1000
2007/01/08  1050
2007/01/09  1100
2007/01/12   900
2007/01/13   880
2007/01/14   870
2007/01/16   920
2007/01/17  1000

株価が、右肩上がりな期間を
以下の形式で出力する。

出力結果
  開始年月    終了年月
----------  ----------
2007/01/06  2007/01/09
2007/01/13  2007/01/17
プログラマのためのSQL第2版の24章[リージョン、ラン、シーケンス]を参考にさせていただきました。


データ作成スクリプト

create table 株価推移 as
select to_date('2007/01/06','yyyy/mm/dd') as 年月,1000 as 株価 from dual
union select to_date('2007/01/08','yyyy/mm/dd'),1050 from dual
union select to_date('2007/01/09','yyyy/mm/dd'),1100 from dual
union select to_date('2007/01/12','yyyy/mm/dd'), 900 from dual
union select to_date('2007/01/13','yyyy/mm/dd'), 880 from dual
union select to_date('2007/01/14','yyyy/mm/dd'), 870 from dual
union select to_date('2007/01/16','yyyy/mm/dd'), 920 from dual
union select to_date('2007/01/17','yyyy/mm/dd'),1000 from dual;


SQL

select min(年月) as 開始年月,max(年月) as 終了年月
from (select 年月,株価,sum(WillSum) over(order by 年月) as makeGroup
      from (select 年月,株価,
            case when lnnvl(株価 > Lag(株価) over(order by 年月))
                 then 1 else 0 end as WillSum
              from 株価推移))
group by makeGroup
having count(*) > 1
order by min(年月);


解説

case式とLag関数とSum関数を組み合わせてます。

Lag関数を使った行間比較がありますので、
旅人算の感覚を使わないほうがシンプルでしょう。

CodeZine:SQLで数列を扱う