SQLite中如何在total(size)超过指定值时提前终止计算?
在SQLite中实现累加阈值提前终止的查询
SQLite内置的total()这类聚合函数会遍历整张表计算总和,无法中途终止。但结合你的表中无负数值的特点,我们可以用递归CTE实现累加至超过阈值后立即停止计算的逻辑,避免遍历全表。
以下是几种可行的实现方案:
方案1:依赖连续rowid的高效实现
如果你的表rowid是连续递增的(无删除记录导致的断号),可以直接用rowid控制遍历顺序:
WITH RECURSIVE cumulative_sum AS ( -- 初始化:取第一条记录的rowid、size值,判断是否已超阈值 SELECT rowid AS rid, SIZE AS current_sum, SIZE > 300 AS is_over FROM sample ORDER BY rowid LIMIT 1 UNION ALL -- 递归阶段:仅当当前累加未超阈值时,取下一条记录累加 SELECT s.rowid, cs.current_sum + s.SIZE, (cs.current_sum + s.SIZE) > 300 FROM cumulative_sum cs JOIN sample s ON s.rowid = cs.rid + 1 WHERE cs.is_over = 0 ) -- 取最终判断结果,表为空时返回0(总和必然不大于300) SELECT COALESCE((SELECT is_over FROM cumulative_sum ORDER BY rid DESC LIMIT 1), 0) AS total_over_300;
方案2:兼容rowid不连续的通用实现
如果表存在删除操作导致rowid断号,先通过ROW_NUMBER()生成连续序号再遍历:
WITH ordered_sample AS ( -- 给每条记录生成连续序号,保证遍历顺序 SELECT SIZE, ROW_NUMBER() OVER (ORDER BY rowid) AS rn FROM sample ), cumulative_sum AS ( SELECT rn, SIZE AS current_sum, SIZE > 300 AS is_over FROM ordered_sample WHERE rn = 1 UNION ALL SELECT os.rn, cs.current_sum + os.SIZE, (cs.current_sum + os.SIZE) > 300 FROM cumulative_sum cs JOIN ordered_sample os ON os.rn = cs.rn + 1 WHERE cs.is_over = 0 ) SELECT COALESCE((SELECT is_over FROM cumulative_sum ORDER BY rn DESC LIMIT 1), 0) AS total_over_300;
逻辑说明
- 递归CTE会从第一条记录开始逐步累加
SIZE值,每次累加后判断是否超过300。 - 一旦累加值超过阈值,
is_over会被标记为1,后续递归会因WHERE cs.is_over = 0的条件停止执行,不会继续遍历剩余记录。 COALESCE用于处理表为空的边界情况,此时直接返回0表示总和不大于300。
内容的提问来源于stack exchange,提问作者Sampath Reddy
相关产品推荐
相关产品推荐

