Вот подход с использованием рекурсивного запроса. Логика c состоит в том, чтобы выполнять итерацию в конце квартала до исчерпания диапазона дат:
with cte as (
select
id,
dateadd(qq, datediff(qq, 0, start_date) + 1, -1) start_date,
end_date,
data
from mytable
union all
select
id,
dateadd(qq, datediff(qq, 0, dateadd(month, 4, start_date)), -1),
end_date,
data
from cte
where start_date < dateadd(qq, datediff(qq, 0, end_date), -1)
)
select cast(start_date as date) start_date, data from cte order by id, start_date
Я добавил столбец id
, чтобы однозначно идентифицировать каждую запись в стартовой таблице. Это не является строго необходимым для запроса, но позволяет правильно упорядочить записи в наборе результатов.
Демонстрация на DB Fiddle
Пример данные:
id | start_date | end_date | data
-: | :--------- | :--------- | ---:
1 | 2015-09-01 | 2016-07-15 | 500
2 | 2016-05-01 | 2017-01-01 | 600
Результаты запроса:
start_date | data
:--------- | ---:
2015-09-30 | 500
2015-12-31 | 500
2016-03-31 | 500
2016-06-30 | 500
2016-06-30 | 600
2016-09-30 | 600
2016-12-31 | 600