Postgresql 中的时间-window 滚动总和
Time-window rolling sum in Postgresql
我想知道是否可以在 Postgresql 中使用 window 基于时间的查询。
原始数据在前三列(日期、业务员、金额):
date
salesman
amount
sum-3-rolling-days
2020-01-01
john
10
10
2020-01-02
john
15
25
2020-01-03
john
8
33
2020-01-04
john
12
35
2020-01-05
john
11
31
2020-01-01
daniel
5
5
2020-01-02
daniel
6
11
2020-01-03
daniel
7
18
2020-01-04
daniel
8
21
2020-01-05
daniel
9
24
第四列表示该销售员在过去三天的总金额。
Pandas 具有执行此操作的内置函数,但我想不出使用内置 sum() over ()
语法在 Postgresql 中执行此操作的任何方法。我能够使用的唯一方法是使用横向连接和子查询的复杂组合以及时间增量比较的条件,这至少可以说是不雅的。
Pandas' 方式(根据记忆,确切的语法可能略有不同)——无法得到任何简洁:
df.groupby('salesman').rolling('3d').sum()
SELECT
*,
SUM(amount) OVER (
PARTITION BY salesman -- 1
ORDER BY "date" -- 2
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW -- 3
)
FROM mytable
- 由
salesman
构建 groups/partitions。所以,以下只会在个分区 内完成
- 按
date
列排序
- 仅对当前日期和当前日期之间的 2 个记录求和。这是滚动部分
如果您使用的是 Postgres 11 或更高版本,您可以使用带日期间隔的 RANGE
更精确地定义 window 而不是计算 ROWS
:
SELECT
*,
SUM(amount) OVER (
PARTITION BY salesman
ORDER BY "date"
RANGE BETWEEN interval '2 days' PRECEDING AND CURRENT ROW
)
FROM mytable
您可以使用CTE(常用table表达式)。
试试
with data as (
select
date,
salesman,
amount
from
foo
group by
date,
salesman
order by
date,
salesman,
)
select
*,
sum(amount) over (
partition by salesman order by date,
salesman rows between unbounded preceding and current row
) as rolling
from data;
我想知道是否可以在 Postgresql 中使用 window 基于时间的查询。
原始数据在前三列(日期、业务员、金额):
date | salesman | amount | sum-3-rolling-days |
---|---|---|---|
2020-01-01 | john | 10 | 10 |
2020-01-02 | john | 15 | 25 |
2020-01-03 | john | 8 | 33 |
2020-01-04 | john | 12 | 35 |
2020-01-05 | john | 11 | 31 |
2020-01-01 | daniel | 5 | 5 |
2020-01-02 | daniel | 6 | 11 |
2020-01-03 | daniel | 7 | 18 |
2020-01-04 | daniel | 8 | 21 |
2020-01-05 | daniel | 9 | 24 |
第四列表示该销售员在过去三天的总金额。
Pandas 具有执行此操作的内置函数,但我想不出使用内置 sum() over ()
语法在 Postgresql 中执行此操作的任何方法。我能够使用的唯一方法是使用横向连接和子查询的复杂组合以及时间增量比较的条件,这至少可以说是不雅的。
Pandas' 方式(根据记忆,确切的语法可能略有不同)——无法得到任何简洁:
df.groupby('salesman').rolling('3d').sum()
SELECT
*,
SUM(amount) OVER (
PARTITION BY salesman -- 1
ORDER BY "date" -- 2
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW -- 3
)
FROM mytable
- 由
salesman
构建 groups/partitions。所以,以下只会在个分区 内完成
- 按
date
列排序 - 仅对当前日期和当前日期之间的 2 个记录求和。这是滚动部分
如果您使用的是 Postgres 11 或更高版本,您可以使用带日期间隔的 RANGE
更精确地定义 window 而不是计算 ROWS
:
SELECT
*,
SUM(amount) OVER (
PARTITION BY salesman
ORDER BY "date"
RANGE BETWEEN interval '2 days' PRECEDING AND CURRENT ROW
)
FROM mytable
您可以使用CTE(常用table表达式)。 试试
with data as (
select
date,
salesman,
amount
from
foo
group by
date,
salesman
order by
date,
salesman,
)
select
*,
sum(amount) over (
partition by salesman order by date,
salesman rows between unbounded preceding and current row
) as rolling
from data;