This is the answer to the question from @Erwin's answer to Postgres Efficient Time Series Query .
To keep things simple, I will use the same table structure as this question
id | widget_id | for_date | score |
The initial question was to get an estimate for each of the widgets for each date in the range. If there was no entry for the widget on the date, then display the rating from the previous entry for this widget. A solution using cross-connect and window function worked well if all the data was in the range that you requested. My problem is that I want to get the previous result, even if it is outside the date range that we are looking at.
Sample data:
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);
When I request a range from May 5 to May 10, 2012 (i.e. generate_series('2012-05-05'::date, '2012-05-10'::date, '1d') ), I would like get the following:
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
The best solution so far (also by @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;
But as you can see in this SQL Fiddle , it produces zero points for widget 1337 in the first two days. I would like to see an earlier score of 52 from row 1 in my place.
Can this be done in an effective way?