4. 「2日前からの累計」
次は移動累計を求めるSQLのアレンジ問題です。『PostgreSQLの分析関数の衝撃2』では、『相関サブクエリで行と行を比較する』の移動累計を求めるSQLを扱いましたが、これをアレンジして2日前からの移動累計を求めるSQLを考えます。
まずは、値を少し変更したテーブルのデータと出力結果を考えます。
prc_date | prc_amt |
2006-10-26 | 100 |
2006-10-28 | 200 |
2006-10-31 | 400 |
2006-11-03 | 800 |
2006-11-04 | 1600 |
2006-11-06 | 3200 |
2006-11-11 | 6400 |
prc_date | prc_amt | mvg_sum |
2006-10-26 | 100 | 100 |
2006-10-28 | 200 | 300 |
2006-10-31 | 400 | 400 |
2006-11-03 | 800 | 800 |
2006-11-04 | 1600 | 2400 |
2006-11-06 | 3200 | 4800 |
2006-11-11 | 6400 | 6400 |
OracleやDB2の分析関数では、range 2 Preceding
といった指定ができますので下記のようなSQLが使えましたが、PostgreSQL 8.4では文法エラーになります。
select prc_date,prc_amt, sum(prc_amt) over(order by prc_date range interVal '2 day' Preceding) as mvg_sum from Accounts;
答えは下記となります。
select prc_date,prc_amt, prc_amt+ case when Lag(prc_date,2) over(order by prc_date) >= prc_date-interVal '2 day' then Lag(prc_amt,2) over(order by prc_date) else 0 end + case when Lag(prc_date) over(order by prc_date) >= prc_date-interVal '2 day' then Lag(prc_amt) over(order by prc_date) else 0 end as mvg_sum from Accounts;
case
式を使って、Lag
関数で2行前のprc_dateを調べ、2日前以降ならprc_amtを加算し、同様に、Lag
関数で1行前のprc_dateを調べ、2日前以降ならprc_amtを加算しています。SQLのイメージは下記となります。
上記のSQLは、2日前からの累計ではなく、75日前からの累計を求める場合などにLag
関数を大量に記述しないといけないので、相関サブクエリで2日前からの累計を求めるSQLを紹介しておきましょう。
select prc_date,prc_amt, (select sum(b.prc_amt) from Accounts b where b.prc_date between a.prc_date-interVal '2 day' and a.prc_date) as mvg_sum from Accounts a;