5

我有一个理论问题,所以我对替代解决方案不感兴趣。对不起。

问:是否可以获得除当前行之外的所有先前行的窗口运行函数值?

例如:

with
  t(i,x,y) as (
    values
      (1,1,1),(2,1,3),(3,1,2),
      (4,2,4),(5,2,2),(6,2,8)
    )
select
  t.*,
  sum(y) over (partition by x order by i) - y as sum,
  max(y) over (partition by x order by i) as max,
  count(*) filter (where y > 2) over (partition by x order by i) as cnt
from
  t;

实际结果是

 i | x | y | sum | max | cnt 
---+---+---+-----+-----+-----
 1 | 1 | 1 |   0 |   1 |   0
 2 | 1 | 3 |   1 |   3 |   1
 3 | 1 | 2 |   4 |   3 |   1
 4 | 2 | 4 |   0 |   4 |   1
 5 | 2 | 2 |   4 |   4 |   1
 6 | 2 | 8 |   6 |   8 |   2
(6 rows)

我想拥有maxcnt列一样的行为sum,所以,结果应该是:

 i | x | y | sum | max | cnt 
---+---+---+-----+-----+-----
 1 | 1 | 1 |   0 |     |   0
 2 | 1 | 3 |   1 |   1 |   0
 3 | 1 | 2 |   4 |   3 |   1
 4 | 2 | 4 |   0 |     |   0
 5 | 2 | 2 |   4 |   4 |   1
 6 | 2 | 8 |   6 |   4 |   1
(6 rows)

可以使用简单的子查询来实现,例如

select t.*, lag(y,1) over (partition by x order by i) as yy from t

但是是否可以只使用窗口函数语法而不使用子查询?

4

1 回答 1

8

是的你可以。这可以解决问题:

with
  t(i,x,y) as (
    values
      (1,1,1),(2,1,3),(3,1,2),
      (4,2,4),(5,2,2),(6,2,8)
    )
select
  t.*,
  sum(y) over w as sum,
  max(y) over w as max,
  count(*) filter (where y > 2) over w as cnt
from t
window w as (partition by x order by i
             rows between unbounded preceding and 1 preceding);

仅从您感兴趣的frame_clause窗口框架中选择那些行。

请注意,在sum列中您将得到null而不是0因为框架子句:框架中的第一行之前没有行。coalesce()如果需要,您可以将其移除。

SQLFiddle

于 2016-03-10T00:49:19.500 回答