SQL:移動平均をwindow関数で求める
移動平均をwindow関数を利用してSQLで求めてみました。DBMSはPostgreSQLのバージョン12を利用しました。
移動平均とは
移動平均は連続するデータの不規則な変化を滑らかにするために用いられます。
不規則なデータの変化を滑らかにすることでそのデータの変化の傾向がつかみやすくなります。
連続するデータのある時点のデータの移動平均はそのデータを含む一定の区間の平均をとることで求められます。
移動平均には区間のとり方によって中央移動平均、後方移動平均、前方移動平均などの種類があり、それぞれの区間のとり方は以下です。
- 中央移動平均 … ある時点のデータとその前後の区間のデータの平均値を使う
- 後方移動平均 … ある時点のデータとその後の区間のデータの平均値を使う
- 前方移動平均 … ある時点のデータとその前の区間のデータの平均値を使う
移動平均の求め方
後方移動平均、前方移動平均については単純にそれぞれの区間の平均値を計算することで求めることができます。
ただし中央移動平均の求め方については区間数を奇数にするか偶数にするかで計算方法が変わってきます。
中央移動平均の区間数が偶数の場合は分子のデータ数が区間数より1つ多くなってしまうので両端の値についてはそれぞれ0.5をかけることで調整を行います。
サンプルデータ
東京電力ホールディングスのサイトからダウンロードできる電力使用実績データの2021年の5月中旬~6月中旬までのデータの使用実績を日ごとに集計してサンプルデータとしました。
SQLで移動平均を求める前にエクセルで計算してみます。
C列の移動平均列は区間数7の中央移動平均です。C6のセルに=ROUND(AVERAGE(B3:B9),0)
を入力してオートフィルでC31まで求めました。
このC列の移動平均が今回SQLで求める答えとなります。
日付 | 実績(万kW) | 移動平均 | |
---|---|---|---|
2021/5/15 | 2607 | ||
2021/5/16 | 2471 | ||
2021/5/17 | 2966 | ||
2021/5/18 | 3018 | 2847 | |
2021/5/19 | 2933 | 2851 | |
2021/5/20 | 2919 | 2854 | |
2021/5/21 | 3018 | 2846 | |
2021/5/22 | 2629 | 2845 | |
2021/5/23 | 2498 | 2845 | |
2021/5/24 | 2906 | 2847 | |
2021/5/25 | 3014 | 2828 | |
2021/5/26 | 2928 | 2828 | |
2021/5/27 | 2935 | 2834 | |
2021/5/28 | 2884 | 2830 | |
2021/5/29 | 2630 | 2823 | |
2021/5/30 | 2540 | 2828 | |
2021/5/31 | 2876 | 2840 | |
2021/6/1 | 2966 | 2866 | |
2021/6/2 | 2962 | 2869 | |
2021/6/3 | 3023 | 2872 | |
2021/6/4 | 3062 | 2893 | |
2021/6/5 | 2654 | 2931 | |
2021/6/6 | 2560 | 2963 | |
2021/6/7 | 3022 | 2993 | |
2021/6/8 | 3233 | 3010 | |
2021/6/9 | 3184 | 3027 | |
2021/6/10 | 3233 | 3047 | |
2021/6/11 | 3182 | 3055 | |
2021/6/12 | 2778 | 3055 | |
2021/6/13 | 2695 | ||
2021/6/14 | 3077 | ||
2021/6/15 | 3239 | ||
移動平均のグラフでは土日に減少する使用実績の変化が滑らかになり6月に入ってから使用実績が少しずつ増加する傾向があることが読み取りやすくなりました。
移動平均をSQLで求める
まず電力使用実績データを入れるテーブルを作成します。
作成した電力使用実績テーブルに先ほどのエクセルのデータを投入します。
それではSQLで先ほどのエクセルの数式と同じく区間数7の中央移動平均を求めます。
区間数7の中央移動平均を求めるので対象のデータから前後に各3個のデータをとる区間をWINDOW句で定義しています。
WINDOW句で定義した区間に対してavg関数をwindow関数として呼び出して平均を求めます。
対象の区間の区間数が7にならない場合はCASE式でNULLを返すようにしました。
データを区間ごとに集計したい場合にwindow関数が便利です。