如何根据oracle中的每日余额预测分期付款?

时间:2015-08-25 16:56:25

标签: sql oracle date-arithmetic

我有一个包含以下simplfied结构的表: 平衡,日期,credit_type。 根据日期和信用类型(每日负载),我需要预测余额的未来流量。 还需要考虑周末和假期, 有什么想法吗?

以下是一些示例数据:

data table          
balance_actual  partner credit_type date
12000            C&A    CRD_type_1  25-08-2015

Rule Table          
credit_type No_Of_Installments  days_due_1st_Installment next_install_days 
 CRD_type_1           2               3                          4

以下是所需的结果集:

balance_forecast    partner credit_type date
6000                 C&A    CRD_type_1  26-08-2015
6000                 C&A    CRD_type_1  27-08-2015
0                    C&A    CRD_type_1  28-08-2015
6000                 C&A    CRD_type_1  29-08-2015
6000                 C&A    CRD_type_1  30-08-2015
6000                 C&A    CRD_type_1  31-08-2015
0                    C&A    CRD_type_1  01-09-2015

所需的balance_forecast = balance_actual / No_Of_Installments。 在2015年8月28日,我的balance_forecast为零,因为days_due_1st_Installment = 3(初始日期后3天)。同样的日期01-09-2015再次归零,因为next_install_day = 4(第一个分期付款日期后4天)。

1 个答案:

答案 0 :(得分:0)

有几个小问题需要解决。

  1. 计算每期的到期日期和大小
  2. 计算预算预测
  3. 生成一个跨越贷款期限的日期矩阵
  4. 有几种方法可以解决它们。 MODEL子句是一个选项,但这非常粗糙。使用一系列子查询更加冗长,但更容易看到发生了什么。

    第一个子查询将LOAN详细信息与其RULE连接起来,并计算贷款的生命周期和每个分期付款的大小。

    with lr as  ( select l.balance_actual
           , l.start_date
           , l.partner
           , l.credit_type
           , r.days_due_1st_Installment 
                      + (r.next_install_days * (r.No_Of_Installments-1)) tot_days
           , (l.balance_actual/r.No_Of_Installments) installment
           , r.days_due_1st_Installment
           , r.next_install_days
           , r.No_Of_Installments
    from loan l
         join rule r
              on l.credit_type = r.credit_type
    

    第二个子查询获取该输出并计算每笔贷款到期的日期,使用CONNECT BY技巧生成一组行:

     , sch as (
        select case when level = 1 then lr.start_date + lr.days_due_1st_Installment
                      else lr.start_date + lr.days_due_1st_Installment
                                   + (lr.next_install_days * (level-1))
                 end as due_date
               , lr.*
        from lr
        connect by level <= lr.No_Of_Installments 
        )
    

    第三个子查询再次使用CONNECT BY技巧生成日期列表:

     , pln as ( select lr.start_date + level as cal_date
                from lr
                connect by level <= lr.tot_days 
         )
    

    主查询使用令人兴奋的连接类型数组连接这些子查询,并使用Analytic SUM()函数计算剩余余额:

    select pln.cal_date
           , sch.installment as install_due
           , lr.balance_actual - nvl((sum(sch.installment) 
                             over (order by pln.cal_date)),0) as forecast_balance
           , lr.credit_type
           , lr.partner
    from lr 
         cross join pln
         left join sch on sch.due_date =  pln.cal_date
    order by pln.cal_date
    ;
    

    请注意,我对FORECAST_BUDGET的计算与发布的计算不同。我认为我的实施更有意义,但OP可能不同意:)

    所以,这就是整个事情:

    with lr as 
      ( select l.balance_actual
               , l.start_date
               , l.partner
               , l.credit_type
               , r.days_due_1st_Installment + (r.next_install_days * (r.No_Of_Installments-1)) tot_days
               , (l.balance_actual/r.No_Of_Installments) installment
               , r.days_due_1st_Installment
               , r.next_install_days
               , r.No_Of_Installments
        from loan l
             join rule r
                  on l.credit_type = r.credit_type
       )
     , sch as (
        select case when level = 1 then lr.start_date + lr.days_due_1st_Installment
                      else lr.start_date + lr.days_due_1st_Installment + (lr.next_install_days * (level-1))
                 end as due_date
                , lr.*
        from lr
        connect by level <= lr.No_Of_Installments 
        )
     , pln as ( select lr.start_date + level as cal_date
                from lr
                connect by level <= lr.tot_days 
         )
    select pln.cal_date
           , sch.installment as install_due
           , lr.balance_actual - nvl((sum(sch.installment) over (order by pln.cal_date)),0) as forecast_balance
           , lr.credit_type
           , lr.partner
    from lr 
         cross join pln
         left join sch on sch.due_date =  pln.cal_date
    order by pln.cal_date
    

    还有a SQL Fiddle here

    日期计算都没有考虑假期或周末。那是因为OP没有说明他们想要的东西,尽管我们可以猜测(即分期和到期日仅为工作日)。

    Oracle没有为假期提供内置解决方案。因此,应用程序必须以自己的方式处理它们。

    周末是有问题的,因为它们是由NLS参数定义的(是你周的第1天或第7天?哪些日子包括周末?)。 Other SO threads tackle this