У меня есть набор данных, который включает клиента, дату платежа и количество дней, за которые он заплатил.Мне нужно рассчитать даты начала / окончания покрытия, которые покрывает каждый платеж.Это сложно, когда платеж производится до окончания текущего периода покрытия.
Лучший способ подумать об этом - ежемесячный тариф на сотовый телефон, когда клиент может заплатить за определенное количество дней в любой момент в течение данного месяца.Следующий покрываемый период всегда должен начинаться на следующий день после истечения срока действия предыдущего покрываемого периода.
Вот пример кода с использованием временной таблицы.
CREATE TABLE #Payments
(Customer_ID INTEGER,
Payment_Date DATE,
Days_Paid INTEGER);
INSERT INTO #Payments
VALUES (1,'2018-01-01',30);
INSERT INTO #Payments
VALUES (1,'2018-01-29',20);
INSERT INTO #Payments
VALUES (1,'2018-02-15',30);
INSERT INTO #Payments
VALUES (1,'2018-04-01',30);
Мне нужно получить начало / конец покрытиявосходит
Первоначальный платеж был сделан 2018-01-01, и они заплатили за 30 дней.Это означает, что они покрываются до 2018-01-30 (Payment_Date + Paid_Days - 1, поскольку дата платежа включена в покрытый день).Однако они произвели следующий платеж 2018-01-29, поэтому мне нужно рассчитать дату начала следующего окна покрытия, которая в этом случае будет предыдущей Payment_Date + previous Paid_Days.В этом случае окно покрытия 2 начинается с 2018-02-01 и продлится до 2018-02-19, так как они платили только за 20 дней с Payment_Date 2018-01-29.
Ожидаемый результат:
Customer_ID | Payment_Date | Days_Paid | Coverage_Start_Date | Coverage_End_Date
--------------------------------------------------------------------------------
1 | '2018-01-01'| 30 | '2018-01-01'| '2018-01-30'
1 | '2018-01-29'| 20 | '2018-01-31'| '2018-02-19'
1 | '2018-02-15'| 30 | '2018-02-20'| '2018-03-21'
1 | '2018-04-01'| 30 | '2018-04-01'| '2018-04-30'
Поскольку дата начала покрытия текущей записи будет зависеть от даты окончания покрытия предыдущей записи, я чувствую, что это будет хорошим кандидатом для рекурсии, ноЯ не могу понять, как это сделать.
У меня есть способ сделать это в цикле while, но я хотел бы завершить его с помощью рекурсивного CTE.Я также подумал о том, чтобы просто добавить Days_Paid и добавить его к дате начала первого платежа, однако это работает только в том случае, если платеж сделан до истечения срока действия предыдущего покрытия.Кроме того, мне нужно рассчитать даты начала / окончания покрытия для каждой даты платежа.
Наконец, использование функций LAG / LEAD, похоже, не работает, поскольку не учитывает результат предыдущей итерации, а только текущее значение предыдущей записи.Используя LAG / LEAD, вы получите правильный ответ для 2-й платежной записи, но не для третьей.
Есть ли способ сделать это с помощью рекурсивного CTE?