By using db<>fiddle, you agree to license everything you submit by Creative Commons CC0.
DROP TABLE IF EXISTS #test;
CREATE TABLE #test (id NVARCHAR(20), yr CHAR(4), mo CHAR(2), yr_mo CHAR(7), val int);
INSERT INTO
#test (id, yr, mo, yr_mo, val)
VALUES
('bob', '2023', '01', '2023_01', 100),
('bob', '2023', '02', '2023_02', 75),
('bob', '2023', '03', '2023_03', 0),
('bob', '2023', '04', '2023_04', 20),
('bob', '2023', '05', '2023_05', 60),
('jennifer', '2023', '01', '2023_01', 0),
('jennifer', '2023', '02', '2023_02', 10);
7 rows affected
DECLARE @start date = (SELECT MIN(DATEFROMPARTS(yr,mo,1)) FROM #test),
@end date = DATEFROMPARTS(YEAR(getdate()),MONTH(getdate()),1),
@select nvarchar(max),
@pivot nvarchar(max),
@sql nvarchar(max);
;WITH x AS
(
SELECT d = DATEADD(MONTH, delta, @start)
FROM
(
SELECT delta = ROW_NUMBER() OVER (ORDER BY @@SPID) - 1
FROM STRING_SPLIT(REPLICATE(',',DATEDIFF(MONTH, @start, @end)),',')
) AS y
),
cols AS
(
SELECT c = QUOTENAME(REPLACE(CONVERT(char(7),d,120), N'-', N'_'))
FROM x
)
SELECT @select = STRING_AGG(CONCAT(c,N' = COALESCE(',c,N',0)'),N','),
@pivot = STRING_AGG(c, N',')
FROM cols;
SET @sql = N'SELECT id, ' + @select + N'
FROM #test
PIVOT (SUM(val) FOR yr_mo IN (' + @pivot + N')) AS pvt;';
PRINT @sql;
EXEC sys.sp_executesql @sql;
id | 2023_01 | 2023_02 | 2023_03 | 2023_04 | 2023_05 | 2023_06 | 2023_07 | 2023_08 | 2023_09 | 2023_10 | 2023_11 | 2023_12 | 2024_01 | 2024_02 | 2024_03 | 2024_04 | 2024_05 | 2024_06 | 2024_07 | 2024_08 | 2024_09 | 2024_10 | 2024_11 | 2024_12 | 2025_01 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
bob | 100 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
bob | 0 | 75 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
bob | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
bob | 0 | 0 | 0 | 20 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
bob | 0 | 0 | 0 | 0 | 60 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
jennifer | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
jennifer | 0 | 10 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
SELECT id, [2023_01] = COALESCE([2023_01],0),[2023_02] = COALESCE([2023_02],0),[2023_03] = COALESCE([2023_03],0),[2023_04] = COALESCE([2023_04],0),[2023_05] = COALESCE([2023_05],0),[2023_06] = COALESCE([2023_06],0),[2023_07] = COALESCE([2023_07],0),[2023_08] = COALESCE([2023_08],0),[2023_09] = COALESCE([2023_09],0),[2023_10] = COALESCE([2023_10],0),[2023_11] = COALESCE([2023_11],0),[2023_12] = COALESCE([2023_12],0),[2024_01] = COALESCE([2024_01],0),[2024_02] = COALESCE([2024_02],0),[2024_03] = COALESCE([2024_03],0),[2024_04] = COALESCE([2024_04],0),[2024_05] = COALESCE([2024_05],0),[2024_06] = COALESCE([2024_06],0),[2024_07] = COALESCE([2024_07],0),[2024_08] = COALESCE([2024_08],0),[2024_09] = COALESCE([2024_09],0),[2024_10] = COALESCE([2024_10],0),[2024_11] = COALESCE([2024_11],0),[2024_12] = COALESCE([2024_12],0),[2025_01] = COALESCE([2025_01],0)
FROM #test
PIVOT (SUM(val) FOR yr_mo IN ([2023_01],[2023_02],[2023_03],[2023_04],[2023_05],[2023_06],[2023_07],[2023_08],[2023_09],[2023_10],[2023_11],[2023_12],[2024_01],[2024_02],[2024_03],[2024_04],[2024_05],[2024_06],[2024_07],[2024_08],[2024_09],[2024_10],[2024_11],[2024_12],[2025_01])) AS pvt;