我想知道您将如何使用 postgres 解决这个问题。 基本上我需要跟踪每个用户的活跃产品(为简单起见,我假设只有一个用户,但会有数千个)。 想象一下,我每天收到活跃产品的每日余额,并将其存储在一个表 (mytable) 中,例如:
天 | 用户 | 每日余额 |
---|---|---|
1 月 1 日 | 用户A | +1 |
1 月 2 日 | 用户A | +3 |
1 月 3 日 | 用户A | -2 |
1 月 4 日 | 用户A | +2 |
1 月 5 日 | 用户A | +1 |
1 月 6 日 | 用户A | -1 |
1 月 7 日 | 用户A | +3 |
(由于数据更正,过去几天的信息可能会发生变化)。
现在我需要计算每天活跃产品(每个用户)的运行总和作为前一天的运行总和加上每日余额 我设法通过这个查询实现了这一点:
SELECT day, user ,
SUM(dailybalance) OVER(PARTITION BY user ORDER BY day)
AS runningtotal
FROM mytable
结果是这样的,其中的值反映到runningtotal列中
天 | 用户 | 每日余额 | 运行总计 |
---|---|---|---|
1 月 1 日 | 用户A | +1 | 1 |
1 月 2 日 | 用户A | +3 | 4 |
1 月 3 日 | 用户A | -2 | 2 |
1 月 4 日 | 用户A | +2 | 4 |
1 月 5 日 | 用户A | +1 | 5 |
1 月 6 日 | 用户A | -1 | 4 |
1 月 7 日 | 用户A | +3 | 7 |
我的问题是,为了计算这个,我需要从一开始就需要所有数据:我不能这样做,因为我们的数据保留政策不允许我们长期存储此类数据(此外我不认为它会在数据集开始变得非常大时进行缩放)。
我就是这么想的 引入时间过滤器并计算/更新 runningtotal,例如,仅针对前 3 天(而不是仅针对最后一天,因为如上所述,我可能会收到过去几天的更正)。 通过这种方式,我可能需要在我的时间过滤器的第一天之前的最后一天存储有关 runningtotal 的信息。 示例:鉴于上面的表格,我想(重新)计算 1 月 5 日 - 1 月 7 日范围内的每日余额,但我需要以某种方式检索 1 月 4 日的运行总计。 我该怎么做? 和/或 postgres 中是否有可能有帮助的内容?
非常感谢!!
答案 0 :(得分:0)
假设您有一个包含存储运行总计的表,请使用 first_value()
计算存储在受限窗口前一行中的总计:
select day, user_, dailybalance,
first_value(stored_total) over w
- first_value(dailybalance) over w
+ sum(dailybalance) over w as runningtotal
from mytable
window w as (partition by user_
order by day
rows between 3 preceding
and current row);
结果:
day | user_ | dailybalance | runningtotal
:--------- | :---- | -----------: | -----------:
2021-01-01 | userA | 1 | 1
2021-01-02 | userA | 3 | 4
2021-01-03 | userA | -2 | 2
2021-01-04 | userA | 2 | 4
2021-01-05 | userA | 1 | 5
2021-01-06 | userA | -1 | 4
2021-01-07 | userA | 3 | 7
答案 1 :(得分:0)
非常感谢@Mike!所以,我正在做的是使用您的查询来更新 mytable 的 stored_total 值,从特定日期重新计算。这将适用于新记录,也适用于更正现有记录:
INSERT INTO mytable (day,user_, key_, stored_total)
(选择 day, user_, day||user_ 作为 key_,
first_value(stored_total) 超过 w
- first_value(dailybalance) 超过 w
+ sum(dailybalance) over w as runningtotal
来自 mytable
其中日 >= '2021-01-11'
窗口 w as (partition by user_
按天订购
前 3 行之间的行
和当前行))
冲突 (key_)
DO UPDATE SET stored_total = exclude.stored_total
https://dbfiddle.uk/?rdbms=postgres_13&fiddle=087301569a03f27113431dfac214e155