Вы можете использовать последовательность CTE для построения данных за пропущенные периоды. В этом запросе первый CTE (EOYS
) генерирует все даты конца года (YYYY-12-31
), относящиеся к таблице; вторая (INTERVALS
) средняя длина интервала для каждого ID
и третья (MISSING
) попытка найти начальную (от t2
) и конечную (от t3
) даты смежных интервалов для любых пропущенных ( обозначено t1.ID IS NULL
) интервалом в конце года. Выходные данные этого CTE затем используются в запросе INSERT ... SELECT
для добавления пропущенных записей интервалов в таблицу, генерируя пропущенные даты, добавляя / вычитая длину интервала к дате окончания / начала соседнего интервала по мере необходимости.
Сначала мы добавим столбец interp
, чтобы указать, была ли строка интерполирована:
ALTER TABLE Table1 ADD interp TINYINT NOT NULL DEFAULT 0;
Это устанавливает interp
в 0
для всех существующих строк. Затем мы можем сделать INSERT
, установив interp
для всех этих строк в 1
:
WITH EOYS AS (
SELECT DISTINCT DATEFROMPARTS(DATEPART(YEAR, interval_beg), 12, 31) AS eoy
FROM Table1
),
INTERVALS AS (
SELECT ID, AVG(DATEDIFF(DAY, interval_beg, interval_end)) AS interval_len
FROM Table1
GROUP BY ID
),
MISSING AS (
SELECT e.eoy,
ids.ID,
i.interval_len,
COALESCE(t2.amount, t3.amount) AS amount,
DATEADD(DAY, 1, t2.interval_end) AS interval_beg,
DATEADD(DAY, -1, t3.interval_beg) AS interval_end
FROM EOYS e
CROSS JOIN (SELECT DISTINCT ID FROM Table1) ids
JOIN INTERVALS i ON i.ID = ids.ID
LEFT JOIN Table1 t1 ON ids.ID = t1.ID
AND e.eoy BETWEEN t1.interval_beg AND t1.interval_end
LEFT JOIN Table1 t2 ON ids.ID = t2.ID
AND DATEADD(MONTH, -1, e.eoy) BETWEEN t2.interval_beg AND t2.interval_end
LEFT JOIN Table1 t3 ON ids.ID = t3.ID
AND DATEADD(MONTH, 1, e.eoy) BETWEEN t3.interval_beg AND t3.interval_end
WHERE t1.ID IS NULL
)
INSERT INTO Table1 (ID, amount, interval_beg, interval_end, interp)
SELECT ID,
amount,
COALESCE(interval_beg, DATEADD(DAY, -interval_len, interval_end)) AS interval_beg,
COALESCE(interval_end, DATEADD(DAY, interval_len, interval_beg)) AS interval_end,
1 AS interp
FROM MISSING
Это добавит в таблицу следующие строки:
ID amount interval_beg interval_end interp
2 10 2017-12-05 2018-01-04 1
2 10 2018-12-16 2019-01-16 1
2 10 2019-12-28 2020-01-27 1
Демонстрация по SQLFiddle