これは、 Postgres での効率的な時系列クエリに対する @Erwin の回答からの質問です。
簡単にするために、その質問と同じテーブル構造を使用します
id | widget_id | for_date | score |
元の質問は、範囲内のすべての日付の各ウィジェットのスコアを取得することでした。日付にウィジェットのエントリがなかった場合は、そのウィジェットの前のエントリのスコアを表示します。クロス結合とウィンドウ関数を使用したソリューションは、クエリ対象の範囲にすべてのデータが含まれている場合にうまく機能しました。私の問題は、対象の日付範囲外であっても、以前のスコアが必要なことです。
サンプルデータ:
INSERT INTO score (id, widget_id, for_date, score) values
(1, 1337, '2012-04-07', 52),
(2, 2222, '2012-05-05', 99),
(3, 1337, '2012-05-07', 112),
(4, 2222, '2012-05-07', 101);
2012 年 5 月 5 日から 5 月 10 日までの範囲 (つまりgenerate_series('2012-05-05'::date, '2012-05-10'::date, '1d')
) をクエリすると、次のようになります。
DAY WIDGET_ID SCORE
May, 05 2012 1337 52
May, 05 2012 2222 99
May, 06 2012 1337 52
May, 06 2012 2222 99
May, 07 2012 1337 112
May, 07 2012 2222 101
May, 08 2012 1337 112
May, 08 2012 2222 101
May, 09 2012 1337 112
May, 09 2012 2222 101
May, 10 2012 1337 112
May, 10 2012 2222 101
これまでの最良の解決策(これも@Erwinによる)は次のとおりです。
SELECT a.day, a.widget_id, s.score
FROM (
SELECT d.day, w.widget_id
,max(s.for_date) OVER (PARTITION BY w.widget_id ORDER BY d.day) AS effective_date
FROM (SELECT generate_series('2012-05-05'::date, '2012-05-10'::date, '1d')::date AS day) d
CROSS JOIN (SELECT DISTINCT widget_id FROM score) AS w
LEFT JOIN score s ON s.for_date = d.day AND s.widget_id = w.widget_id
) a
LEFT JOIN score s ON s.for_date = a.effective_date AND s.widget_id = a.widget_id
ORDER BY a.day, a.widget_id;
しかし、このSQL Fiddleでわかるように、最初の 2 日間はウィジェット 1337 のスコアが null になります。その代わりに、行 1 の以前のスコア 52 を表示したいと思います。
これを効率的な方法で行うことは可能ですか?