如何在ClickHouse中维护滚动累计余额?
实现滚动累计余额的正确窗口函数用法
嘿,我懂你遇到的困扰了——本来想靠窗口函数做滚动累计,结果发现单纯拿上一行的结果来加,没法把累计值传递到下一行,越算越不对对吧?其实你要的就是滚动累计(Running Total),这事儿用窗口函数的SUM()就能轻松搞定,根本不用手动递推上一行的值!
核心思路
窗口函数里的SUM(Val) OVER()可以直接计算从第一行到当前行的累计和,它会自动把之前所有行的Val加起来,完美对应你要的“当前行Val + 上一行累计结果”的逻辑。关键是要指定按日期排序,确保累计是按时间顺序进行的。
具体示例
假设你的表叫balance_table,结构是Date DATE, Val INT,我们来写个完整的例子:
1. 测试数据(模拟你的表)
CREATE TABLE balance_table ( Date DATE, Val INT ); INSERT INTO balance_table VALUES ('2024-01-01', 100), ('2024-01-02', 50), ('2024-01-03', -30), ('2024-01-04', 200);
2. 滚动累计查询语句
SELECT Date, Val, SUM(Val) OVER (ORDER BY Date) AS Rolling_Balance FROM balance_table;
3. 查询结果
| Date | Val | Rolling_Balance |
|---|---|---|
| 2024-01-01 | 100 | 100 |
| 2024-01-02 | 50 | 150 |
| 2024-01-03 | -30 | 120 |
| 2024-01-04 | 200 | 320 |
你看,这个Rolling_Balance就是你要的滚动余额:每一行都是当前Val加上之前所有行的累计结果,完全符合需求!
为什么你之前的方法不行?
如果之前你用了LAG()函数,比如尝试Val + LAG(Rolling_Balance) OVER(ORDER BY Date),这会陷入死循环——因为Rolling_Balance本身就是你要计算的列,窗口函数没法引用还没计算出来的值。而SUM() OVER(ORDER BY Date)是窗口函数的原生累计逻辑,它会在内部按顺序计算从第一行到当前行的总和,不需要手动处理递推。
扩展:如果需要分组累计
要是你的表还有其他维度(比如不同用户的余额),只需要加PARTITION BY子句就行,比如:
SELECT User_ID, Date, Val, SUM(Val) OVER (PARTITION BY User_ID ORDER BY Date) AS User_Rolling_Balance FROM user_balance_table;
这样就能按每个用户单独计算滚动余额啦!
内容的提问来源于stack exchange,提问作者RandomGuy
相关产品推荐
相关产品推荐

