如何使用SQL窗口函数基于最新余额计算每笔交易的历史累计余额?
问题原因
你的代码存在两处核心逻辑错误:
- 交易变动计算逻辑错误:每笔交易对余额的实际影响是
存款金额 - 取款金额(存款增加余额、取款减少余额),你错误将存款和取款金额相加求和。 - 窗口帧范围错误:你将当前行的交易计入了求和范围,而
latest_balance本身就是最新交易完成后的余额,计算时仅需要累加当前交易之后发生的所有交易的净变动即可。
解决方案
按交易日期倒序排序后,窗口求和范围限定为排序后位于当前行之前的所有行(也就是交易时间晚于当前行的所有交易),正确代码如下:
SELECT *, latest_balance - ISNULL( SUM(deposit - withdrawal) OVER( PARTITION BY account ORDER BY date DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ), 0) AS transaction_balance FROM 你的表名
逻辑说明
按date DESC倒序排序时,最新的交易排在第一行:
- 最新交易的窗口求和范围不存在符合条件的行,求和结果为0,计算得到的
transaction_balance就是latest_balance,符合预期。 - 更早交易的余额会自动扣除后续所有交易的净变动,反向推导的结果和正向累加的余额完全一致。
如果同一账户同一天存在多笔交易,建议在ORDER BY后补充交易序号、交易流水号等唯一排序字段,避免顺序错乱导致计算结果错误。
内容的提问来源于stack exchange,提问作者user16462786
相关产品推荐
相关产品推荐

