Я бы использовал подсчет для этого.Я держу один в моей системе как молниеносный вид.Вот вид.
create View [dbo].[cteTally] as
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
select N from cteTally
GO
Тогда нам понадобятся некоторые примерные данные.Примерно так.
declare @Something table
(
Contract char(1)
, StartDate date
, EndDate date
)
insert @Something values
('A', '20161101', '20180601')
, ('B', '20170531', '20190601')
Теперь мы можем запросить образец и использовать таблицу подсчета для краткой обработки этого.
select s.Contract
, ContractYear = datepart(year, DATEADD(month, t.N - 1, s.StartDate))
, NumMonths = count(*)
from @Something s
join cteTally t on t.N <= datediff(month, s.StartDate, s.EndDate) + 1
group by s.Contract
, datepart(year, DATEADD(month, t.N - 1, s.StartDate))
order by s.Contract
, datepart(year, DATEADD(month, t.N - 1, s.StartDate))