PostgreSQLで指定した期間の連続した日付を作成します。
やりたいこと
例えば、FROM:2021-04-01、TO:2021-04-30と指定した場合、
2021-04-01
2021-04-02
2021-04-03
(中略)
2021-04-30
といった連続した日付を持った一時的なテーブルを作成します。
月間の実績を日毎に累積して表示してほしい、という要件があったのですが、
単純に実績データのみを取得すると、実績がある日付しか表示されません。
そこで上記の一時テーブルと実績テーブルを外部結合して累積することで対応しました。
(SQLのみで実装する必要はあるのか、という点はおいといて、、、)
やりかた
generate_seriesを使用します。
generate_seriesは集合を返す関数です。
詳しくは公式マニュアルを読んでください。
PostgreSQL 12.4文書-9.24. 集合を返す関数
実行例
SELECT
generate_series::DATE AS date
FROM
generate_series('2021-04-01'::DATE, '2021-04-30'::DATE, '1 day');
※戻り型はTIMESTAMP型のためDATE型にキャストしています。
実行結果
date
2021-04-01
2021-04-02
2021-04-03
2021-04-04
2021-04-05
2021-04-06
2021-04-07
2021-04-08
2021-04-09
2021-04-10
2021-04-11
2021-04-12
2021-04-13
2021-04-14
2021-04-15
2021-04-16
2021-04-17
2021-04-18
2021-04-19
2021-04-20
2021-04-21
2021-04-22
2021-04-23
2021-04-24
2021-04-25
2021-04-26
2021-04-27
2021-04-28
2021-04-29
2021-04-30
(30 rows)
おまけ
月間の実績を累積して取得する例
WITH dates AS (
SELECT
generate_series::DATE AS date
FROM
generate_series('2021-04-01'::DATE, '2021-04-30'::DATE, '1 day')
)
, achievements AS (
SELECT
'2021-04-05'::DATE AS date
, 100 AS value
UNION ALL
SELECT
'2021-04-10'::DATE AS date
, 150 AS value
UNION ALL
SELECT
'2021-04-15'::DATE AS date
, 300 AS value
)
SELECT
dates.date
, SUM(COALESCE(achievements.value, 0)) OVER (ORDER BY dates.date) AS value
FROM
dates
LEFT JOIN achievements ON
achievements.date = dates.date;
実行結果
date | value
2021-04-01 | 0
2021-04-02 | 0
2021-04-03 | 0
2021-04-04 | 0
2021-04-05 | 100
2021-04-06 | 100
2021-04-07 | 100
2021-04-08 | 100
2021-04-09 | 100
2021-04-10 | 250
2021-04-11 | 250
2021-04-12 | 250
2021-04-13 | 250
2021-04-14 | 250
2021-04-15 | 550
2021-04-16 | 550
2021-04-17 | 550
2021-04-18 | 550
2021-04-19 | 550
2021-04-20 | 550
2021-04-21 | 550
2021-04-22 | 550
2021-04-23 | 550
2021-04-24 | 550
2021-04-25 | 550
2021-04-26 | 550
2021-04-27 | 550
2021-04-28 | 550
2021-04-29 | 550
2021-04-30 | 550
(30 rows)