在MySQL中计算截止日期未付的累计还款总额

66bbxpm5  于 2022-11-21  发布在  Mysql
关注(0)|答案(2)|浏览(202)

我 有 一 个 还款 表 , 看 起来 像 下面 这样 ,
| 客户 标识|到期 日|本金|支付 日期|
| - -| - -| - -| - -|
| 一 个|2022 年 1 月 1 日|10 个|2021 年 11 月 1 日|
| 一 个|2022 年 2 月 1 日|10 个|2021 年 11 月 1 日|
| 一 个|2022 年 3 月 1 日|10 个|2021 年 11 月 1 日|
| 2 个|2022 年 3 月 15 日|二十 个|2022 年 2 月 15 日|
| 一 个|2022 年 4 月 1 日|10 个|2021 年 11 月 1 日|
| 三 个|2022 年 4 月 1 日|十五|2022 年 3 月 20 日|
| 2 个|2022 年 4 月 15 日|二十 个|2022 年 2 月 15 日|
| 三 个|2022 年 5 月 1 日|十五|2022 年 3 月 20 日|
| 2 个|2022 年 5 月 30 日|二十 个|2022 年 2 月 15 日|
| 一 个|2022 年 5 月 30 日|10 个|2021 年 11 月 1 日|
| 三 个|2022 年 6 月 1 日|十五|2022 年 3 月 20 日|
| 2 个|2022 年 6 月 15 日|二十 个|2022 年 2 月 15 日|
| 2 个|2022 年 6 月 30 日|二十 个|2022 年 2 月 15 日|
| 三 个|2022 年 7 月 1 日|五十五 人|2022 年 3 月 20 日|
一 个 人 可以 * * 在 * * 月 * * 的 任何 一 天 * * 支付 任何 金额 , 也 可以 * * 同一 客户 * * 在 * * 一 个 月 * * 内 * * 支付 * * 2 次 * * 。 * * * dispensed _ day * * * 是 支付 日( 可能 是 第 一 次 EMI 之前 的 任何 一 天 ) , 并且 对于 每个 cus _ id 都 是 相同 的 。 每个 客户 的 总 金额 是 sum(principal) group by cus_id , 即 客户 1 、 2和 3 总量 分别 为 50 、 100 和 100 。
我 想 计算 截至 每个 * * * due _ date * * * 的 未 付 金额 。 预期 结果 如下 所 示 :

| date_as_of   | outstanding |                                            |
| ------------ | ----------- | ------------------------------------------ |
| 01-01-2022   | 40          |  -- total outstanding as on 50, paid 10    |
| 01-02-2022   | 30          |  -- cus1 paid emi 10                       |
| 01-03-2022   | 120         |  -- amt for 2 disbursed on 15-02, 20+100   |
| 15-03-2022   | 100         |  -- cus2 paid emi of 20                    |
| 01-04-2022   | 175         |  -- amt for 3 disbursed on 20-03, 10+80+85 |
| 15-04-2022   | 155         |  -- cus2 paid emi of 20                    |
| 01-05-2022   | 140         |  -- cus3 paid emi of 15                    |
| 30-05-2022   | 110         |                                            |
| 01-06-2022   | 95          |                                            |
| 15-06-2022   | 75          |                                            |
| 30-06-2022   | 55          |                                            |
| 01-07-2022   | 0           |                                            |

中 的 每 一 个
对于 2 月 1 日 的 EMI , 客户 1 支付 了 10 的 2 EMI , 因此 截至 2 月 1 日 的 未 付 金额 为 50 - ( 10 + 10 ) = 30 。
对于 3 月 1 日 的 EMI , 客户 1 支付 了 10 的 3 EMI 。 客户 2 在 2 月 15 日 支付 了 100 的 金额 , 因此 截至 3 月 1 日 的 未 付 金额 将 为 ( 50 - ( 10 + 10 + 10 ) ) +100 = 120
3 月 15 日 , 客户 2 支付 了 20 的 EMI , 因此 未 付 金额 为 ( 50 - ( 10 + 10 + 10 ) ) + ( 100 - 20 ) = 100
对于 4 月 1 日 的 EMI , 客户 1 支付 了 4 个 EMI , 金额 为 10 。 客户 2 支付 了 1 个 EMI , 金额 为 20 ( 3 月 15 日 ) 。 客户 3 的 金额 在 3 月 20 日 支付 , 但 还 支付 了 15 个 EMI 。 因此 未 付 金额 将 为 ( 50 - ( 10 + 10 + 10 + 10 ) ) + ( 100 - 20 ) + ( 100 - 15 ) = 175
这 就是 计算 未 付 款项 的 方法 。 我 在 下面 尝试 了 这种 方法 ,

select *, (osp_as_on - principal) balance from (
    select due_date, principal, sum(net_repayment) over(order by due_date desc) osp_as_on from (
        select due_date, principal, sum(principal) net_repayment
            from repayments
        group by 1
    ) t1 
) t2 order by 1;

格式
但 我 的 方法 是 不 正确 的 , 因为 我 的 查询 没有 考虑 * * * dispensed _ date * * * , 因为 只有 在 支付 日期 之后 , 我 才 必须 考虑 总额 中 的 余额 , 以 计算 截至 到期 日 的 正确 未 付 款项 。
如果 有 任何 来自 社区 的 帮助 , 我 将 不胜 感激 。 我 使用 的 是 MySQL8.0 。

bvuwiixz

bvuwiixz1#

一种方法是将列解透视为行,这样我们就可以正确地计算任何时间点的窗口总和,然后过滤掉不相关的行(即那些对应于“支付日期”的行)。

select date_as_of, outstanding
from (
    select x.*
        sum(x.outstanding) over(order by x.date_as_of) outstanding
    from mytable t
    cross join lateral (
        select t.disbursed_date as date_as_of, t.principal as outstanding, 0 keep_row
        union all select t.due_date, - t.principal, 1
    ) x
) t
where keep_row
order by date_as_of

对于示例数据,此函数将返回:
| 截止日期|突出的|
| - -|- -|
| 2022年1月1日|四十|
| 2022年2月1日|三十|
| 2022年3月1日|一百二十|
| 2022年3月15日|100个|
| 2022年4月1日|一百七十五|
| 2022年4月1日|一百七十五|
| 2022年4月15日|一百五十五|
| 2022年5月1日|一百四十个|
| 2022年5月30日|第一百一十章|
| 2022年5月30日|第一百一十章|
| 2022年6月1日|九十五|
| 2022年6月15日|七十五|
| 2022年6月30日|五十五|
| 2022年7月1日|第0页|


njthzxwz

njthzxwz2#

这可以通过3个步骤完成:
1.计算到期日之前的未付金额和支付日期之前的付款金额(cte1)
1.计算截止日期的累计未付金额(cte2)
1.筛选出不报告的行。

with cte1 as (
select disbursed_date  as date_as_of,
       sum(principal)  as outstanding,
       false           as report_flag
  from mytable
 group by 1
 union all 
select due_date        as date_as_of,
       sum(-principal) as outstanding,
       true            as report_flag
  from mytable
 group by 1),
cte2 as (
select date_as_of,
       sum(outstanding) over (order by date_as_of) as outstanding,
       report_flag
  from cte1)
select date_as_of,
       outstanding
  from cte2
 where report_flag
 order by 1;

结果:

date_as_of|outstanding|
----------+-----------+
2022-01-01|         40|
2022-02-01|         30|
2022-03-01|        120|
2022-03-15|        100|
2022-04-01|        175|
2022-04-15|        155|
2022-05-01|        140|
2022-05-30|        110|
2022-06-01|         95|
2022-06-15|         75|
2022-06-30|         55|
2022-07-01|          0|

相关问题