Postgresql 使用Postgres窗口函数获取相对于每行的日期范围的平均值

Postgresql 使用Postgres窗口函数获取相对于每行的日期范围的平均值,postgresql,Postgresql,该问题需要使用PostgreSQL 9.4窗口函数(不带GROUP BY)计算过去12个月内每行的平均值 例如: MY_DATE VALUE NEW_VALUE REGION_ID 2016-09-01 11 1 2016-10-01 22 1 2016-11-01 33 1 2016-12-01 44 1 2017-01-01 55

该问题需要使用PostgreSQL 9.4窗口函数(不带GROUP BY)计算过去12个月内每行的平均值

例如:

MY_DATE     VALUE   NEW_VALUE  REGION_ID
2016-09-01  11                 1
2016-10-01  22                 1
2016-11-01  33                 1
2016-12-01  44                 1    
2017-01-01  55                 1    
2017-02-01  66                 1    
2017-03-01  77                 1    
2017-04-01  88                 1    
2017-05-01  99                 1    
2017-06-01  11                 1    
2017-07-01  22                 1    
2017-08-01  33      46.75      1
2017-09-01  44      49.5       1
2017-10-01  55      52.25      1
研究我得到了平均值,但仅限于确切日期:

-- Works, but for exact dates:

SELECT *, AVG(value) FILTER (
WHERE my_date > '2016-09-01'
  AND my_date < '2017-10-01') OVER (PARTITION BY region_id)
FROM my_table;

-- Precalculating extra field period_start_date = my_date - INTERVAL '12 month' doesn't work as expected:

SELECT *, AVG(value) FILTER (
WHERE my_date > period_start_date
  AND my_date < period_start_date + INTERVAL '12 MONTH') OVER (PARTITION BY region_id)
FROM my_table;
问题: 如何获得预期的选择结果?允许多个查询,但没有过程


PostgreSQL 11在窗口函数中添加了对范围间隔的支持。此功能正是针对此类问题而设计的

您可以使用相关子查询

SELECT t1.*,
       (SELECT avg(t2.value)
               FROM my_table t2
               WHERE t2.region_id = t1.region_id
                     AND t2.my_date <= t1.my_date
                     AND t2.my_date > t1.my_date - '1 year'::interval)
       FROM my_table t1;

谢谢不幸的是,该项目是在Postgres 9.4。记录的数量是否固定为每年12个?在这种情况下,我们可以将间隔之间的范围更改为前11行和当前行之间的行。12个月与年无关。它是相对于当前行的。但是在PostResql9.4中没有介于两者之间的范围。答案是9.4。是的,范围特征不存在,但行特征存在;但这只有在每年有12个记录的情况下才有效;但是,无论如何,另一个解决方案在你的案例中更好,在9.4版中效果很好。非常感谢。
SELECT t1.*,
       (SELECT avg(t2.value)
               FROM my_table t2
               WHERE t2.region_id = t1.region_id
                     AND t2.my_date <= t1.my_date
                     AND t2.my_date > t1.my_date - '1 year'::interval)
       FROM my_table t1;