SQL优化查询:获取满足累计(B-C)和阈值条件的行(含MySQL方案)
没问题!针对你这个按累计B-C求和取行的需求,我分别给你整理MySQL和Informix的实现方案,完全贴合你的示例场景~
首先咱们先确认表结构(假设表名叫your_table):
| A | B | C | D |
|---|---|---|---|
| o1 | 100 | 20 | i1 |
| o2 | 100 | 30 | i1 |
需求核心:按D分组,从第一行开始累计计算B-C的值,直到累计和≥给定的目标值,返回所有参与累加的行。
MySQL 解决方案
如果你的MySQL版本是8.0及以上,用窗口函数+CTE的方式最简洁高效,逻辑也清晰:
-- 先设置目标参数,你可以换成实际传入的值 SET @target_d = 'i1'; SET @target_value = 100; WITH cumulative_rows AS ( -- 计算同D组内,按A排序的累计求和值 SELECT A, B, C, D, SUM(B - C) OVER (PARTITION BY D ORDER BY A) AS cumulative_sum FROM your_table WHERE D = @target_d ), min_reach_sum AS ( -- 找到第一个≥目标值的累计和(也就是最小的达标累计值) SELECT MIN(cumulative_sum) AS min_sum FROM cumulative_rows WHERE cumulative_sum >= @target_value ) -- 返回所有累计和≤达标值的行,也就是所有参与累加的行 SELECT c.A, c.B, c.C, c.D FROM cumulative_rows c JOIN min_reach_sum m ON c.cumulative_sum <= m.min_sum ORDER BY c.A;
示例验证
- 当
@target_value=80时,min_sum为80,只返回o1(刚好满足条件) - 当
@target_value=100时,min_sum为150(80+70),返回o1和o2(累加后才满足条件)
Informix 解决方案
Informix的实现分两种情况,取决于你的版本是否支持窗口函数:
情况1:Informix 12.10及以上(支持窗口函数+CTE)
语法和MySQL非常接近,直接适配即可:
-- 定义目标参数 DEFINE target_d CHAR(2); DEFINE target_value INT; LET target_d = 'i1'; LET target_value = 100; WITH cumulative_rows AS ( SELECT A, B, C, D, SUM(B - C) OVER (PARTITION BY D ORDER BY A) AS cumulative_sum FROM your_table WHERE D = target_d ), min_reach_sum AS ( SELECT MIN(cumulative_sum) AS min_sum FROM cumulative_rows WHERE cumulative_sum >= target_value ) SELECT c.A, c.B, c.C, c.D FROM cumulative_rows c, min_reach_sum m WHERE c.cumulative_sum <= m.min_sum ORDER BY c.A;
情况2:旧版本Informix(不支持窗口函数)
用自连接的方式实现累计求和,分两步执行:
-- 定义目标参数 DEFINE target_d CHAR(2); DEFINE target_value INT; DEFINE min_reach_a CHAR(2); LET target_d = 'i1'; LET target_value = 100; -- 第一步:找到第一个累计和≥目标值的行的A值 SELECT t1.A INTO min_reach_a FROM your_table t1 WHERE t1.D = target_d AND ( SELECT SUM(t2.B - t2.C) FROM your_table t2 WHERE t2.D = t1.D AND t2.A <= t1.A ) >= target_value ORDER BY t1.A FETCH FIRST 1 ROW ONLY; -- 第二步:返回所有到该A值的行 SELECT A, B, C, D FROM your_table WHERE D = target_d AND A <= min_reach_a ORDER BY A;
示例验证
两种写法都能实现:
- 目标值80时,返回
o1 - 目标值100时,返回
o1和o2
内容的提问来源于stack exchange,提问作者Raghunandan J
相关产品推荐
相关产品推荐

