平均难以定义分区

Clo*_*eto 5 sql postgresql null aggregate-functions window-functions

我有这张桌子:

create table t (value int, dt date);

 value |     dt     
-------+------------
    10 | 2012-10-30
    15 | 2012-10-29
  null | 2012-10-28
  null | 2012-10-27
     7 | 2012-10-26
Run Code Online (Sandbox Code Playgroud)

我想要这个输出:

 value |     dt     
-------+------------
    10 | 2012-10-30
     5 | 2012-10-29
     5 | 2012-10-28
     5 | 2012-10-27
     7 | 2012-10-26
Run Code Online (Sandbox Code Playgroud)

我希望当表按日期降序排序时,空值以及前一个非空值将替换为先前非空值的平均值.在此示例中,值15是接下来的两个空值的先前非空值.所以15/3 = 5.

SQL小提琴

Erw*_*ter 4

我发现了一个令人惊讶的简单解决方案:

SELECT max(value) OVER (PARTITION BY grp)
      / count(*)  OVER (PARTITION BY grp) AS value
      ,dt
FROM   (
   SELECT *, count(value) OVER (ORDER BY dt DESC) AS grp
   FROM   t
   ) a;
Run Code Online (Sandbox Code Playgroud)

-> sqlfiddle

由于count()忽略NULL值,您可以使用运行计数(窗口函数中的默认值)来快速对值进行分组 (-> grp)。

每个组都有一个非空值,因此我们可以使用 min / max / sum 在另一个窗口函数中获得相同的结果。除以 中的成员数量(count(*)这次是为了计算NULL值!),grp我们就完成了。