Запрос Amazon Redshift для получения просроченной суммы и просроченных дней в конце месяца - PullRequest
0 голосов
/ 22 ноября 2018

Изменение вопроса из-за недопонимания в случае использования.

Amazon Redshift Запрос на следующую формулировку проблемы.

Структура данных:

  1. id -первичный ключ
  2. acc_id - уникальный идентификатор для ссудного счета (этот идентификатор будет одинаковым для всех emi для определенного ссудного счета, это может повторяться 6 или 12 раз в зависимости от срока кредита, который может составлять 6 месяцев или 12).месяцев соответственно)
  3. статус - оплачено или неоплачено (за неоплаченным emi следуют только мои неоплаченные emi)
  4. s_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

Вариант использования -

Неоплаченная сумма становится просроченной (просроченной) по истечении срока платежа.

Поэтому мне нужно рассчитать сумму просроченного платежа в конце каждого месяца от первой даты платежа в этом случаеЭто 2 июля до последнего срока платежа (предположим, что это 2 ноября, который является текущим месяцем)

Мне также нужно рассчитать просроченные дни в конце этого месяца.

Иллюстрация извышеуказанные данные:

  • Из предоставленных выборочных данных в конце июля не должно быть никаких EMI, поэтому сумма просрочки составляет 0
  • Но в конце августа - идентификатор 9999958- по состоянию на 31 августа сумма просроченной задолженности составляет 4100, а просроченные дни - 29 (31 августа минус 2 августа)

Подвох: мне нужно рассчитать это для кредита (acc_id), а не для EMI.

Для более подробного объяснения, первая EMI будет составлять 29 дней в первый месяц и 59 дней - во второй месяц, а вторая EMI будет 29 дней - во второй месяц. Но мне это нужно на уровне займа (acc_id).

Тот же пример продолжался 30 сентября, acc_id 10003 должен быть оплачен со 2 августа, поэтому по состоянию на 30 сентября сумма задолженности составляет 8366 (4100 + 4266) и DPD (days_past_due) - 59 (29 + 30).

Также acc_id 10004 - 3100, а DPD - 28 (30 сентября - 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 могут быть созданы на основе заявлений case в дни просрочки.Мне нужна реальная помощь, чтобы сначала создать «Конец месяцев», а затем найти суммы уровня портфеля, как описано выше для разных просроченных дней.

1 Ответ

0 голосов
/ 22 ноября 2018

Отредактировано для совместимости с 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
...