Amazon Redshift 查询以在月底获取拖欠金额和逾期天数

Posted

技术标签:

【中文标题】Amazon Redshift 查询以在月底获取拖欠金额和逾期天数【英文标题】:Amazon Redshift query to get delinquent amount and days past due at the end of month 【发布时间】:2018-11-22 10:15:51 【问题描述】:

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

Amazon Redshift 查询以下问题陈述。

数据结构:

    id - 主键 acc_id - 贷款账户唯一的 ID(此 ID 对所有账户都相同) emi 用于特定的贷款账户,这可能重复 6 次或 12次基于贷款期限,可以是6个月或12个月 分别) status - PAID 或 UNPAID (emi 的 unpaid 跟 my unpaid 仅限emi) s_id - 只是一个调度 ID,它是一个连续的数字 特定的贷款 ID due_date - 特定 emi 的截止日期 本金 - 到期金额

桌子:

   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 日)

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

以上数据说明:

从提供的样本数据来看,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 带。我需要真正的帮助来首先创建月末,然后按照上述不同拖欠日期的说明查找投资组合级别的金额。

【问题讨论】:

我已经删除了所有那些冲突的 dbms 标签。将其中一个放回去,用于实际使用的 dbms。 指定预期结果以及格式化文本。并向我们​​展示您当前的查询尝试。 好的,新来的。感谢您的关注。 为什么是mysql标签?这是mysql还是redshift? 数据在 mysql 和 Redshift 上都可用。 【参考方案1】:

在操作澄清了哪个 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

也就是说,通常像这样旋转事物的想法是一个坏主意。当某件事逾期一年时会发生什么?它只是属于 90+ 类别,从不移动。而且,如果您想扩展它,您需要更改查询以及您编写的任何其他依赖于它的查询。

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

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

【讨论】:

这是完美的垫子。但是你能看到我更新的用例吗?唯一额外的是,而不是单个 emi,总和(本金)应该是该特定用户日期之前的所有未付贷款。 和dpd应该从第一笔未偿还的贷款开始计算 嘿,Mat,你能帮我更新一下用例吗?我可以提供更多的理解,我真的很挣扎 您要我创建另一个问题吗?

以上是关于Amazon Redshift 查询以在月底获取拖欠金额和逾期天数的主要内容,如果未能解决你的问题,请参考以下文章

Amazon Redshift:获取最新的行查询

Amazon Redshift - 复制 - 数据加载与查询性能问题

Amazon Redshift - 按类别获取每周销售量

使用 Amazon Redshift 从 Python psycopg2 中的游标获取大于 MAX INT 的行数

Amazon Redshift:是不是可以返回多个结果集?

使用 Amazon Redshift / PostgreSQL 进行漏斗查询