【发布时间】:2013-10-26 20:47:34
【问题描述】:
这是@Erwin 对Efficient time series querying in 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 Fiddle 中看到的那样,它在前两天为小部件 1337 生成空分数。我想看看之前第 1 行的 52 分。
是否有可能以有效的方式做到这一点?
【问题讨论】:
标签: sql postgresql time-series greatest-n-per-group generate-series