Window 运行 除当前行外的函数
Window running function except current row
我有一个理论问题,所以我对替代解决方案不感兴趣。对不起。
问:是否可以获取所有先前行的 window 运行 函数值,当前行除外?
例如:
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
但是是否可以仅使用 window 函数语法而不使用子查询?
是的,你可以。这就是诀窍:
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
仅从 window 框架中选择您感兴趣的那些行。
请注意,在 sum
列中,您将得到 null
而不是 0
,因为 frame 子句:框架中的第一行之前没有行。如果需要,您可以 coalesce()
删除它。
我有一个理论问题,所以我对替代解决方案不感兴趣。对不起。
问:是否可以获取所有先前行的 window 运行 函数值,当前行除外?
例如:
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
但是是否可以仅使用 window 函数语法而不使用子查询?
是的,你可以。这就是诀窍:
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
仅从 window 框架中选择您感兴趣的那些行。
请注意,在 sum
列中,您将得到 null
而不是 0
,因为 frame 子句:框架中的第一行之前没有行。如果需要,您可以 coalesce()
删除它。