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

PySpark中如何基于前一日数据递推计算当日日初、日终余额

账户日初/日终余额按日递推计算方案

业务场景

  • 每月1日存在初始余额字段saldo,后续日期需按日逐次核算交易金额变动,计算每日的日初余额begin_day与日终余额end_day
  • 计算逻辑遍历整月所有日期数据,非月初日期计算时始终取前一日的计算结果,结合当日交易数据运算

原始计算逻辑(伪代码)

if 日期为当月1日 then
do;
begin_day = saldo + trans - vl_dis + vl_car + vl_ret;
end_day = saldo ;
end;
if 日期大于当月1日 then
do;
begin_day = 前一日end_day;
end_day = begin_day - trans + vl_dis - vl_car - vl_ret;
end;

实现说明

普通lag()窗口函数仅能读取上一行的原始字段值,无法递归引用上一行计算生成的end_day字段,无需编写递归CTE,通过累计求和窗口即可实现逻辑,以Spark/Hive SQL为例:

SELECT 
    key,
    saldo,
    trans,
    vl_dis,
    vl_car,
    vl_ret,
    day,
    CASE WHEN rn = 1 
        THEN saldo + trans - vl_dis + vl_car + vl_ret
        ELSE LAG(end_day, 1) OVER (PARTITION BY key, date_trunc('month', day) ORDER BY day)
    END AS begin_day,
    CASE WHEN rn = 1 
        THEN saldo
        ELSE FIRST_VALUE(saldo) OVER (PARTITION BY key, date_trunc('month', day) ORDER BY day) 
            + SUM(-trans + vl_dis - vl_car - vl_ret) OVER (
                PARTITION BY key, date_trunc('month', day) 
                ORDER BY day 
                ROWS BETWEEN 1 FOLLOWING AND CURRENT ROW
            )
    END AS end_day
FROM (
    SELECT 
        *,
        ROW_NUMBER() OVER (PARTITION BY key, date_trunc('month', day) ORDER BY day) AS rn
    FROM your_balance_table
) t

期望输出结果

keysaldotransvl_disvl_carvl_retbegin_dayend_dayday
123100.01.02.00.00.099.0100.02022-02-01
1230.01.00.00.00.0100.099.02022-02-02
1230.01.00.00.00.099.098.02022-02-03
1230.01.00.00.00.098.097.02022-02-04
1230.01.02.00.00.097.098.02022-02-05
1230.01.00.00.00.098.097.02022-02-06
1230.01.00.00.00.097.096.02022-02-07
1230.01.02.00.00.096.097.02022-02-08
1230.01.00.00.00.097.096.02022-02-09

内容的提问来源于stack exchange,提问作者Carlos Eduardo Bilar Rodrigues

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:24:28