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

如何计算表中每行Opening值为上一行Opening与Transfer之和?

重新计算Opening列的高效方案

你的核心需求是:当前行的Opening = 上一行的Opening + 上一行的Transfer,第一行Opening为初始值。不需要用游标或while循环,窗口函数或递归CTE是更高效、简洁的实现方式,前提是你的表有一个能确定行顺序的字段(比如自增row_id)。

方案1:使用窗口函数(MySQL 8.0+/PostgreSQL/SQL Server)

用LAG()函数直接获取上一行的Opening值,结合计算逻辑生成正确的Opening:

SELECT
    CASE
        WHEN row_id = 1 THEN Opening
        ELSE LAG(Opening) OVER (ORDER BY row_id) + LAG(Transfer) OVER (ORDER BY row_id)
    END AS Opening,
    Transfer
FROM your_table
ORDER BY row_id;

或者用累计求和的方式,逻辑等价但更简洁:

SELECT
    (SELECT Opening FROM your_table WHERE row_id = 1) + 
    COALESCE(SUM(Transfer) OVER (ORDER BY row_id ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), 0) AS Opening,
    Transfer
FROM your_table
ORDER BY row_id;

方案2:递归CTE(支持递归的数据库)

如果需要更贴合“逐行计算”的逻辑,递归CTE是直观的选择:

WITH cte AS (
    -- 第一行作为初始数据
    SELECT row_id, Opening, Transfer
    FROM your_table
    WHERE row_id = 1
    
    UNION ALL
    
    -- 递归计算后续行
    SELECT
        t.row_id,
        c.Opening + c.Transfer AS Opening,
        t.Transfer
    FROM your_table t
    JOIN cte c ON t.row_id = c.row_id + 1
)
SELECT Opening, Transfer FROM cte ORDER BY row_id;

方案3:旧版MySQL(无窗口函数)

如果使用MySQL 5.x这类不支持窗口函数的版本,用用户变量实现:

-- 初始化变量为第一行的Opening值
SET @prev_opening = (SELECT Opening FROM your_table WHERE row_id = 1);

SELECT
    @prev_opening AS Opening,
    Transfer,
    -- 更新变量,供下一行计算使用
    @prev_opening := @prev_opening + Transfer
FROM your_table
ORDER BY row_id;

为什么游标/while循环容易失效?

  • 游标需要手动处理行顺序、变量更新,稍有疏忽就会出现逻辑错误(比如漏更改变量、顺序判断错误)
  • While循环依赖id的连续性,如果表中存在删除行导致id断号,循环会直接终止,而上述方案只需要排序字段存在,不依赖id连续

测试结果

用你的示例数据验证,以上方案都会输出正确的表格:

OpeningTransfer
012
12-2
10-2
8-1
7-7

内容的提问来源于stack exchange,提问作者Jordan P

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 02:05:23