SQL新手求助:提取家庭预算数据库中各账户当前余额
提取各银行账户当前余额的SQL解决方案
核心思路
每个账户的当前余额是该账户最后一笔交易后的余额。由于交易日期无时间戳,当日多笔交易的存储顺序不代表实际发生顺序,但你提到当日最后一笔交易的余额最低,因此可以通过「按账户分组,先按交易日期降序、再按余额升序」排序,取每组的第一条记录余额即可。
解决方案代码(支持CTE的数据库:PostgreSQL、MySQL 8+、SQL Server等)
WITH ranked_transactions AS ( SELECT `Bank Account`, `Bank Account Balance After Transaction` AS current_balance, ROW_NUMBER() OVER ( PARTITION BY `Bank Account` ORDER BY `Date of Transaction` DESC, `Bank Account Balance After Transaction` ASC ) AS rn FROM your_budget_table -- 替换成你的实际表名 ) SELECT `Bank Account`, current_balance FROM ranked_transactions WHERE rn = 1;
代码解释
- CTE临时表:
ranked_transactions给每个账户的交易添加排序序号rn:PARTITION BY Bank Account:将数据按账户分组,每个账户独立处理ORDER BY Date of Transaction DESC:优先取最新日期的交易ORDER BY ... Bank Account Balance After Transaction ASC:同一日期内,按余额从小到大排序,确保取到当日最后一笔交易的余额(即当日最终余额)
- 筛选结果:取每个分组中序号为1的记录,就是对应账户的当前余额
兼容老版本数据库的写法(无CTE支持)
SELECT `Bank Account`, `Bank Account Balance After Transaction` AS current_balance FROM ( SELECT `Bank Account`, `Bank Account Balance After Transaction`, ROW_NUMBER() OVER ( PARTITION BY `Bank Account` ORDER BY `Date of Transaction` DESC, `Bank Account Balance After Transaction` ASC ) AS rn FROM your_budget_table -- 替换成你的实际表名 ) AS t WHERE rn = 1;
为什么你的原有方法出错?
直接用MAX(Date of Transaction)搭配MIN(Bank Account Balance After Transaction)的聚合方式,会导致MAX(日期)和MIN(余额)是独立计算的——可能会把某个账户的最新日期,和该账户所有交易里的最小余额(未必是最新日期的)组合在一起,得到错误结果。同时这种聚合方式没有建立日期和余额的对应关联,自然无法正确按账户分组得到唯一结果。
内容的提问来源于stack exchange,提问作者Bronica
相关产品推荐
相关产品推荐

