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

按perm_id按月累计到期剔除还款额时SAS SQL重叠贷款计算异常求助

解决重叠贷款下按月累计还款并到期剔除的SAS方案

你的核心问题是原SQL自连接逻辑错误(反向累加了未来还款),且未考虑贷款到期后的剔除规则。正确的逻辑应该是:对每个企业的每个月,仅统计处于存续期内(还款日期在贷款起止区间内)的贷款还款,并累计该部分金额;当贷款到期后,后续累计不再包含该贷款的新增还款。

以下是两种可行的解决方案:

方案一:使用SQL窗口函数(推荐)

先计算每笔贷款自身的累计还款,再按月过滤未到期贷款的累计值求和:

/* 第一步:转换贷款起止为SAS日期,计算每笔贷款的累计还款 */
proc sql;
create table loan_cum as
select perm_id,
       date,
       repayment,
       /* 将startyear转换为当年1月1日的SAS日期 */
       mdy(1, 1, startyear) as loan_start format=YYMMN6.,
       /* 将endyear转换为当年12月31日的SAS日期 */
       mdy(12, 31, endyear) as loan_end format=YYMMN6.,
       /* 按贷款分组,计算每笔贷款截至当前月的累计还款 */
       sum(repayment) over(partition by perm_id, startyear, endyear order by date) as loan_total
from work.want;
quit;

/* 第二步:按月汇总所有未到期贷款的累计还款 */
proc sql;
create table want_final as
select perm_id,
       date,
       /* 仅累加当前月仍未到期的贷款的累计还款 */
       sum(case when date <= loan_end then loan_total else 0 end) as cumulative_repayment
from loan_cum
group by perm_id, date
order by perm_id, date;
quit;

方案二:使用数据步事件法

通过生成贷款开始/结束事件,计算每月有效还款额后再累计:

/* 生成贷款事件:开始月+每月还款额,到期次月-每月还款额 */
data loan_events;
set work.want;
by perm_id startyear endyear;
/* 仅为每笔贷款生成一次事件(按startyear+endyear标识同一笔贷款) */
if first.endyear then do;
    /* 贷款开始月事件:增加每月还款额 */
    event_date = mdy(1, 1, startyear);
    amount = repayment;
    output;
    /* 贷款到期次月事件:扣除每月还款额 */
    event_date = intnx('month', mdy(12, 31, endyear), 1);
    amount = -repayment;
    output;
end;
keep perm_id event_date amount;
run;

/* 获取所有需要统计的日期(原数据日期+事件日期) */
proc sql;
create table all_dates as
select distinct perm_id, date from work.want
union
select perm_id, event_date as date from loan_events;
quit;

/* 合并事件与日期,计算每月有效还款额的变动 */
proc sql;
create table monthly_changes as
select a.perm_id,
       a.date,
       sum(coalesce(b.amount, 0)) as monthly_effective
from all_dates a
left join loan_events b on a.perm_id = b.perm_id and a.date = b.event_date
group by a.perm_id, a.date
order by perm_id, date;
quit;

/* 计算累计还款额 */
data want_final;
set monthly_changes;
by perm_id date;
retain cumulative_repayment;
/* 每个企业初始化累计值 */
if first.perm_id then cumulative_repayment = 0;
/* 累加每月有效还款额 */
cumulative_repayment + monthly_effective;
run;

原代码错误说明

  1. 自连接条件b.date >= a.date逻辑反向:你需要的是累计截至当前月的还款,而非当前月到未来的还款,正确条件应为b.date <= a.date,但即使修正也无法处理到期剔除。
  2. 未过滤贷款存续期:未判断还款日期是否在贷款起止区间内,导致提前计入未开始的贷款还款,或持续计入已到期贷款的还款。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 00:47:05