我有一个理论问题,所以我对替代解决方案不感兴趣。遗憾。
问:是否可以让窗口运行所有先前行的函数值,除了当前的行?
例如:
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)
我希望max
和cnt
列的行为类似于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
但是是否可以仅使用窗口函数语法,而不使用子查询?
答案 0 :(得分:2)
是的,你可以。这就是诀窍:
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
列中,由于frame子句,您将获得null
而不是0
:框架中的第一行没有行。如果需要,你可以coalesce()
离开。