SQL如何逐行计算累计值:计算Account_ID 1的账户交易余额
SQL实现账户逐行累计余额计算方法
这类逐行计算交易后账户余额的需求,在SQL中可以非常方便的实现,主流方案是使用窗口函数,低版本数据库也可以用子查询实现。
方案1:窗口函数(推荐,性能好,语法简洁)
窗口函数是SQL标准中专门用于这类跨行计算的语法,支持MySQL 8.0+、PostgreSQL、SQL Server、Oracle、Hive、Spark SQL等几乎所有主流新版数据库。
假设你的交易表名为transaction_records,核心字段如下:
account_id:账户IDtransaction_time:交易发生时间,用于确定交易顺序transaction_amount:交易金额,支出存为负数、收入存为正数
针对Account_ID为1、初始余额为500的计算代码如下:
SELECT account_id, transaction_time, transaction_amount, -- 初始余额 + 累计到当前行的交易金额总和 500 + SUM(transaction_amount) OVER ( PARTITION BY account_id ORDER BY transaction_time ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS account_balance FROM transaction_records WHERE account_id = 1 ORDER BY transaction_time ASC;
语法说明
PARTITION BY account_id:按账户ID分区,每个账户的累计计算独立ORDER BY transaction_time ASC:按交易时间排序,保证累计顺序和交易发生顺序一致ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW:指定求和范围为当前分区的第一行到当前行,实现逐行累加的效果
如果你的表中是单独存储收支类型和正数金额,也可以通过CASE语句转换后计算:
SELECT account_id, transaction_time, amount, 500 + SUM(CASE WHEN is_income = 1 THEN amount ELSE -amount END) OVER ( PARTITION BY account_id ORDER BY transaction_time ASC ) AS account_balance FROM transaction_records WHERE account_id = 1 ORDER BY transaction_time ASC;
方案2:关联子查询(兼容低版本不支持窗口函数的数据库)
如果你使用的是不支持窗口函数的低版本数据库,比如MySQL 5.x,可以用关联子查询实现,缺点是数据量大的时候性能较差:
SELECT t1.account_id, t1.transaction_time, t1.transaction_amount, 500 + ( SELECT SUM(t2.transaction_amount) FROM transaction_records t2 WHERE t2.account_id = t1.account_id AND t2.transaction_time <= t1.transaction_time ) AS account_balance FROM transaction_records t1 WHERE t1.account_id = 1 ORDER BY t1.transaction_time ASC;
内容的提问来源于stack exchange,提问作者AATU
相关产品推荐
相关产品推荐

