大型数据集上的 Postgres 计算运行总和

时间:2021-01-22 17:17:52

标签: postgresql

我想知道您将如何使用 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 中是否有可能有帮助的内容?

非常感谢!!

2 个答案:

答案 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

Fiddle here

答案 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

相关问题