如何用SQL实现带0下限限制的SUM()窗口函数?
实现带下限的累加列(SUM_FUNC_LIMIT)的SQL方案
要生成满足「累加结果小于0则取0,否则保留累加值」的SUM_FUNC_LIMIT列,由于该逻辑依赖前一行的计算结果,普通SUM()窗口函数无法直接实现,以下是两种通用解决方案:
方案一:递归CTE(适用于MySQL 8.0+、PostgreSQL、SQL Server等支持递归的数据库)
假设你的表名为your_table,包含ROW(行号,注意是关键字需用反引号包裹)和AMOUNT列,递归CTE可以逐行计算带限制的累加值:
WITH RECURSIVE cte AS ( -- 初始化第一行数据 SELECT `ROW`, AMOUNT, SUM(AMOUNT) OVER (ORDER BY `ROW`) AS SUM_FUNC, GREATEST(AMOUNT, 0) AS SUM_FUNC_LIMIT FROM your_table WHERE `ROW` = 1 UNION ALL -- 递归计算后续行 SELECT t.`ROW`, t.AMOUNT, c.SUM_FUNC + t.AMOUNT AS SUM_FUNC, GREATEST(c.SUM_FUNC_LIMIT + t.AMOUNT, 0) AS SUM_FUNC_LIMIT FROM your_table t JOIN cte c ON t.`ROW` = c.`ROW` + 1 ) SELECT * FROM cte ORDER BY `ROW`;
逻辑说明:
- 初始行取表中第一行数据,
SUM_FUNC_LIMIT直接取金额与0的最大值 - 后续行通过关联前一行的递归结果,计算新的累加值后再与0取最大,实现带限制的累加逻辑
方案二:用户变量(适用于MySQL 5.x等不支持递归CTE的老版本数据库)
利用用户变量保存前一行的计算结果,逐行迭代更新:
SELECT `ROW`, AMOUNT, @sum_func := @sum_func + AMOUNT AS SUM_FUNC, @sum_limit := GREATEST(@sum_limit + AMOUNT, 0) AS SUM_FUNC_LIMIT FROM your_table, (SELECT @sum_func := 0, @sum_limit := 0) AS init ORDER BY `ROW`;
逻辑说明:
- 初始化两个变量
@sum_func和@sum_limit分别保存普通累加和带限累加的前一行结果 - 按行号排序后,逐行更新变量值,
GREATEST()函数实现小于0取0的限制
以你提到的示例验证:
- 行5金额为-6时,若前一行
SUM_FUNC_LIMIT为2,计算得2 + (-6) = -4,取0作为当前行的SUM_FUNC_LIMIT - 行6金额为3时,0 + 3 = 3,直接保留3作为当前行的
SUM_FUNC_LIMIT
内容的提问来源于stack exchange,提问作者truecount
相关产品推荐
相关产品推荐

