Amazon Redshift查询以获取月底到期的欠款额和过期天数

时间:2018-11-22 10:15:52

标签: mysql sql amazon-redshift

由于对用例的误解而改变了问题。

Amazon Redshift查询以下问题声明。

数据结构:

  1. id-主键
  2. acc_id-贷款帐户唯一的ID(所有用户的ID均相同)         emi的特定贷款帐户,可能重复6次或         根据贷款期限分12次,可能为6个月或12个月         分别)
  3. 状态-PAID或UNPAID(emi的未付款项跟着我的未付款项     仅限emi)
  4. s_id-只是一个调度ID,该ID将是     特定的贷款ID
  5. due_date-该特定emi的截止日期
  6. 本金-到期金额

表格:

   id       acc_id status   s_id    due_date            principal
9999957     10003   PAID    102  2018-07-02 12:00:00        4205
9999958     10003   UNPAID  103  2018-08-02 12:00:00        4100
9999959     10003   UNPAID  104  2018-09-02 12:00:00        4266
9999960     10003   UNPAID  105  2018-10-02 12:00:00        4286
9999962     10004   PAID    106  2018-07-02 12:00:00        3200
9999963     10004   PAID    107  2018-08-02 12:00:00        3100
9999964     10004   UNPAID  108  2018-09-02 12:00:00        3266
9999965     10004   UNPAID  109  2018-10-02 12:00:00        3286

用例-

未付款项在到期日之后变为拖欠(过期)。

因此,我需要计算从本月的第一个到期日到7月2日到最后一个到期日(假设是当月的11月2日)在每个月底的拖欠金额 < / p>

我还需要计算该月底到期的天数。

来自以上数据的插图:

  • 从提供的样本数据来看,7月底没有EMI,因此欠款金额为0
  • 但是在8月底-ID 9999958到期-从8月31日起 欠款金额为4100,逾期天数为29(8月31日减去8月2日)

收获:我需要为贷款(acc_id)而不是emi进行计算。

进一步说明,第一个EMI将在第一个月到期29天,第二个月将到期59天,第二EMI也将在第二个月到期29天。 但是我需要在贷款级别(acc_id)。

同一示例继续到9月30日,acc_id 10003自8月2日起到期,因此从9月30日起,到期金额为8366(4100 + 4266),DPD(days_past_due)为59(29 + 30)。

acc_id 10004也应为3100,DPD为28(9月30日至9月2日)。

最终输出将是这样的:

Month_End   DPD_Band    Amount
2018/08/31  0-29        4100
2018/08/31  30-59       0
2018/08/31  60-89       0
2018/08/31  90+         0
2018/09/30  0-29        3100
2018/09/30  30-59       8366
2018/09/30  60-89       0
2018/09/30  90+         0

查询尝试:DPD波段可以根据拖欠日期的个案陈述来创建。我需要真正的帮助,首先要创建月末,然后按上述在不同的拖欠天数中找到投资组合级别的金额。

1 个答案:

答案 0 :(得分:0)

在操作说明了哪个RDBMS之后,编辑为与RedShift兼容。 (MySQL需要一个不同的答案)

以下内容为您的第一条记录到上个月末之间的每个月创建一个记录。

然后将其加入您的未付款记录中,然后聚合选择将结果放入哪个括号。

WITH
  first_month AS
(
  SELECT LAST_DAY(MIN(due_date)) AS end_date FROM yourTable
),
  months AS
(
  SELECT
    LAST_DAY(ADD_MONTHS(first_month.end_date, s.id))    AS end_date
  FROM
    first_month
  CROSS JOIN
    generate_series(
      1,
      DATEDIFF(month, (SELECT end_date FROM first_month), CURRENT_DATE)
    )
      AS s(id)
),
  monthly_delinquents AS
(
  SELECT
    yourTable.*,
    months.end_date                                        AS month_end_date,
    DATEDIFF(DAY, yourTable.due_date, months.end_date)     AS days_past_due
  FROM
    months
  LEFT JOIN
    yourTable
      ON  yourTable.status   = 'UNPAID'
      AND yourTable.due_date < months.end_date
)
SELECT
  month_end_date,
  SUM(CASE WHEN days_past_due >= 00 AND days_past_due < 30 THEN principal ELSE 0 END)  AS dpd_00_29,
  SUM(CASE WHEN days_past_due >= 30 AND days_past_due < 60 THEN principal ELSE 0 END)  AS dpd_30_59,
  SUM(CASE WHEN days_past_due >= 60 AND days_past_due < 90 THEN principal ELSE 0 END)  AS dpd_60_89,
  SUM(CASE WHEN days_past_due >= 90                        THEN principal ELSE 0 END)  AS dpd_90plus
FROM
  monthly_delinquents
GROUP BY
  month_end_date
ORDER BY
  month_end_date

也就是说,通常将这样的事情变为现实的想法不是一个好主意。当一年到期的时候会发生什么?它只属于90plus类别,永远不会移动。而且,如果要扩展它,则需要更改查询以及您曾经编写的任何依赖此查询的查询。

相反,您可以标准化输出...

WITH
  first_month AS
(
  SELECT LAST_DAY(MIN(due_date)) AS end_date FROM yourTable
),
  months AS
(
  SELECT
    LAST_DAY(ADD_MONTHS(first_month.end_date, s.id))    AS end_date
  FROM
    first_month
  CROSS JOIN
    generate_series(
      1,
      DATEDIFF(month, (SELECT end_date FROM first_month), CURRENT_DATE)
    )
      AS s(id)
),
  monthly_delinquents AS
(
  SELECT
    yourTable.*,
    months.end_date                                        AS month_end_date,
    DATEDIFF(DAY, yourTable.due_date, months.end_date)     AS days_past_due
  FROM
    months
  LEFT JOIN
    yourTable
      ON  yourTable.status   = 'UNPAID'
      AND yourTable.due_date < months.end_date
)
SELECT
  month_end_date,
  (days_past_due / 30) * 30   AS days_past_due_band,
  SUM(principal)              AS total_principal,
  COUNT(*)                    AS total_rows
FROM
  monthly_delinquents
GROUP BY
  month_end_date,
  (days_past_due / 30) * 30
ORDER BY
  month_end_date,
  (days_past_due / 30) * 30