Если у вас есть годы в таблице, вы можете сделать такой динамический круг, это избавит вас от объявления столбцов вручную:
CREATE TABLE #Data (ID int, StartDate date, EndDate date);
CREATE TABLE #Year (y int);
SET DATEFORMAT MDY;
insert into #Data
values
(1, '1/1/2016','4/23/2019'),
(2, '1/1/2016','4/30/2017'),
(3, '1/1/2016','12/31/2018'),
(4, '1/1/2017','4/23/2019'),
(5, '5/20/2017','11/30/2017')
;
insert into #Year
values
(2016),
(2017),
(2018),
(2019)
;
DECLARE
@PivotColumnNames AS NVARCHAR(MAX),
@DynamicPivotQuery AS NVARCHAR(MAX);
SELECT
@PivotColumnNames = ISNULL(@PivotColumnNames + ',','') + QUOTENAME(Y)
FROM
#Year;
SELECT
@DynamicPivotQuery =
'SELECT
ID,
StartDate,
EndDate,'
+ @PivotColumnNames +
'FROM
(
select
ID,
StartDate,
EndDate,
Y,
case
when StartDate >= DATEFROMPARTS(Y+1, 1, 1) or EndDate < DATEFROMPARTS(Y, 1, 1) then 0
when StartDate < DATEFROMPARTS(Y, 1, 1) and EndDate >= DATEFROMPARTS(Y+1, 1, 1) then 12
when StartDate >= DATEFROMPARTS(Y, 1, 1) and EndDate >= DATEFROMPARTS(Y+1, 1, 1) then 13 - MONTH(StartDate)
when StartDate < DATEFROMPARTS(Y, 1, 1) then month(EndDate)
else MONTH(EndDate) + 1 - MONTH(StartDate)
end M
from
#Data, #Year
) as SourceTable
PIVOT
(
SUM(M)
FOR Y IN ('
+ @PivotColumnNames +
')
) as PivotTable';
SELECT @DynamicPivotQuery;
EXEC sp_executesql @DynamicPivotQuery;
DROP TABLE #Data, #Year;