Рекурсивный столбец суммы CTE в SUM с использованием столбца даты в качестве условия завершения - PullRequest
0 голосов
/ 04 августа 2020

У меня есть таблица, содержащая данные о ссуде, включая дату начала, срок ссуды (сколько месяцев будет длиться ссуда) и ежемесячный платеж. Я пытаюсь создать рекурсивный CTE, который будет возвращать СУММУ платежей, произведенных каждый месяц за последние 12 месяцев.

CREATE TABLE [dbo].[loan](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [starting_date] [date] NULL,
    [loan_term] [int] NULL,
    [monthly_payment] [decimal](19, 2) NULL
) ON [PRIMARY]
GO

Пример данных:

INSERT INTO [dbo].[loan]
    ([starting_date]
    ,[loan_term]
    ,[monthly_payment])
VALUES
    ('8/1/2020', 52, 1),
    ('6/2/2010', 64, 2500),
    ('9/11/2011', 66, 650),
    ('7/4/2011', 36, 600),
    ('11/19/2014', 36, 450),
    ('4/21/2017', 24, 650),
    ('6/25/2009', 68, 7500),
    ('4/3/2016', 72, 12000),
    ('5/2/2013', 12, 330),
    ('7/11/2011', 32, 331.33),
    ('6/11/2013', 36, 200),
    ('7/11/2014', 34, 250),
    ('8/15/2015', 32, 673),
    ('9/15/2017', 31, 8),
    ('11/6/2019', 64, 65),
    ('10/13/2017', 52, 128)
GO

Вот что я пробовал :

WITH loanCTE as 
(
-- Anchor Member
SELECT monthly_payment, DATEADD(month, loan_term, starting_date) as loan_end_date, starting_date, starting_date as current_month
    FROM loan

UNION ALL
-- Recursive Member
SELECT monthly_payment, loan_end_date, starting_date, DATEADD(month, 1, current_month)
    FROM loanCTE
    WHERE current_month < loan_end_date -- Terminating condition
)

SELECT  YEAR(current_month) as Year, MONTH(current_month) as Month,  SUM(monthly_payment) as total_montly_payments
    FROM loanCTE
    WHERE Current_Month BETWEEN GETDATE()-365 AND GETDATE()
    GROUP BY YEAR(current_month), MONTH(current_month) 
    ORDER BY YEAR(current_month) DESC, MONTH(current_month) DESC;

который возвращает это:

Year    Month   total_montly_payments
2020    8   12001.00
2020    7   12193.00
2020    6   12193.00
2020    5   12193.00
2020    4   12201.00
2020    3   12201.00
2020    2   12201.00
2020    1   12201.00
2019    12  12201.00
2019    11  12201.00
2019    10  12136.00
2019    9   12136.00
2019    8   136.00

Я могу сказать, что это неверно, потому что в 2019-08 должно быть 12202.00 в total_monthly_payments, а в 2020-08 должно быть 12194.00 в total_monthly_payments, но я Я не уверен, где я ошибаюсь. Кажется, либо способ увеличения текущего месяца в рекурсивном члене, либо что-то с окончательным запросом отключено, но в настоящее время я застрял. Приветствуются любые советы!

1 Ответ

1 голос
/ 04 августа 2020

Я думаю, ваш запрос работает нормально, поскольку вы фильтруете записи за последний год, поэтому сначала фильтруется текущий месяц (на самом деле проблема возникает из-за значения дня в current_month, мы должны использовать первую дату месяца для получить правильные результаты), а затем для полученного набора выполняется агрегирование. Вы можете сначала объединить записи, а затем применить фильтр позже, как показано ниже:

;WITH loanCTE as 
(
-- Anchor Member
SELECT monthly_payment, DATEADD(MM, loan_term, starting_date) as loan_end_date, starting_date, starting_date as current_month
    FROM loan
UNION ALL
-- Recursive Member
SELECT monthly_payment, loan_end_date, starting_date, DATEADD(MM, 1, current_month)
    FROM loanCTE
    WHERE current_month < loan_end_date -- Terminating condition
)
,
temp as
(
    SELECT  YEAR(current_month) as [Year], MONTH(current_month) as [Month],  SUM(monthly_payment) as total_montly_payments
    FROM loanCTE
    GROUP BY YEAR(current_month), MONTH(current_month) 
)

SELECT *
FROM temp
WHERE datefromparts(YEAR, MONTH, 1) BETWEEN GETDATE()-365 AND GETDATE()
ORDER BY [Year] DESC, [Month] DESC

Кроме того, для 201908 общее количество будет 12136,0 из следующего:

('4/3/2016 ', 72, 12000), --12000

(' 15.09.2017 ', 31, 8), --8

(' 13.10.2017 ', 52, 128) --128

Найдите здесь db <> fiddle .

...