You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在ClickHouse中使用窗口函数计算带上限的累计求和

在ClickHouse中实现带上限的累计求和

要实现你描述的sumWithCeil功能(累计求和不超过指定上限,且达到上限后不再继续累加),直接用sum(least(probability, 1)) over (...)或者least(sum(probability) over (...), 1)都不行——前者是先对单个值取最小再累加,后者只是对当前累计值做截断,但后续行仍会继续累加超出上限的部分再截断,都达不到你要的效果。

方法一:用数组函数实现(兼容所有ClickHouse版本)

通过数组批量处理每个分组的累计值,确保一旦累计到上限,后续所有值都保持上限:

SELECT 
    groupId,
    probability,
    datetime,
    runningSum,
    desiredSum
FROM (
    SELECT 
        groupId,
        -- 计算原始累计和数组
        arrayCumSum(probability) AS runningSumArray,
        -- 生成带上限的累计数组:前一个累计值+当前值,超过上限就固定为1
        arrayMap(
            (prev_sum, curr_val) -> least(prev_sum + curr_val, 1),
            -- 在累计数组前补0,对应第一个值的前序累计为0
            arrayPushFront(arrayCumSum(probability), 0),
            probability
        ) AS desiredSumArray,
        probability,
        datetime,
        -- 生成索引用于后续展开数组
        arrayEnumerate(probability) AS idx
    FROM myTable
    GROUP BY groupId
    ORDER BY groupId, datetime ASC
)
-- 展开数组,还原成每行数据
ARRAY JOIN 
    runningSumArray AS runningSum,
    desiredSumArray AS desiredSum,
    idx
ORDER BY groupId, datetime ASC

方法二:用自定义聚合函数+状态窗口函数(ClickHouse 21.8+)

如果你的ClickHouse版本够新(21.8及以上),可以自定义一个聚合函数,结合runningAccumulate来模拟你想要的sumWithCeil:

首先创建自定义聚合函数:

CREATE AGGREGATE FUNCTION sum_with_ceil(max_value Float64)
RETURNS Float64
AGGREGATES (state Float64)
INITIALIZE WITH 0
UPDATE WITH (state + value) -> least(state + value, max_value)
MERGE WITH (a, b) -> least(a + b, max_value)
FINALIZE WITH state;

然后直接在窗口函数中调用:

SELECT 
    groupId,
    value AS probability,
    datetime,
    sum(probability) OVER (PARTITION BY groupId ORDER BY datetime ASC) AS runningSum,
    runningAccumulate(sum_with_ceil(1))(probability) OVER (PARTITION BY groupId ORDER BY datetime ASC) AS desiredSum
FROM myTable t;

两种方法的区别

  • 方法一不用依赖高版本,逻辑直观,适合所有环境;
  • 方法二的调用方式更贴近你虚构的sumWithCeil,代码更简洁,但要求ClickHouse版本支持自定义聚合函数。

内容的提问来源于stack exchange,提问作者Tom Weisner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 01:45:24