这是对 @Erwin 的答案在Postgres中高效查询时间序列的跟进问题。
为了保持简单,我将使用与该问题相同的表结构。
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示例中所看到的,它会在前两天为小部件1337生成空分数。我希望能够看到第一行中52的早期得分。
有没有一种高效的方法来实现这个需求?