This can be done using the UNPIVOT and PIVOT in SQL Server. If you have a known number of columns, you can use the static version:
select clientid, col, year, isnull([1], 0) [1], isnull([2], 0) [2], isnull([3], 0) [3], isnull([4], 0) [4], isnull([5], 0) [5], isnull([6], 0) [6], isnull([7], 0) [7], isnull([8], 0) [8], isnull([9], 0) [9], isnull([10], 0) [10], isnull([11], 0) [11], isnull([12], 0) [12], (isnull([1], 0) + isnull([2], 0) + isnull([3], 0) + isnull([4], 0) + isnull([5], 0) + isnull([6], 0) + isnull([7], 0) + isnull([8], 0) + isnull([9], 0) + isnull([10], 0) + isnull([11], 0) + isnull([12], 0) ) Total from ( select clientid, col, month, year, value from yourtable unpivot ( value for col in (ColumnValue1, ColumnValue2, ColumnValue3) ) u ) x pivot ( sum(value) for month in ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12]) ) p
See SQL Fiddle with Demo
But for this operation it can be much easier to use dynamic sql, then there is less code to write, and this will change the number of months based on what you have in your example data:
DECLARE @colsUnpivot AS NVARCHAR(MAX), @query AS NVARCHAR(MAX), @colsPivot as NVARCHAR(MAX), @colsTotal as NVARCHAR(MAX), @colsNull as NVARCHAR(MAX) select @colsUnpivot = stuff((select ','+ quotename(C.name) from sys.columns as C where C.object_id = object_id('yourtable') and C.name like 'ColumnValue%' for xml path('')), 1, 1, '') select @colsPivot = STUFF((SELECT distinct ', ' + quotename(Month) from yourtable t FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'') select @colsNull = STUFF((SELECT distinct ', IsNull(' + quotename(Month) + ', 0) as '+quotename(Month) from yourtable t FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'') select @colsTotal = STUFF((SELECT distinct '+ IsNull(' + quotename(Month) + ', 0)' from yourtable t FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'') set @query = 'select clientid, year, ' +@colsNull +', ' +@colsTotal +' as Total from ( select clientid, col, month, year, value from yourtable unpivot ( value for col in (' +@colsUnpivot +') ) u ) x pivot ( sum(value) for month in('+ @colspivot +') ) p' exec(@query)
See SQL Fiddle with Demo
Both will give the same results, the difference is that the second will be adjusted based on the data in your table:
| CLIENTID | YEAR | 1 | 2 | TOTAL | ------------------------------------- | 1 | 2012 | 20 | 25 | 45 | | 1 | 2012 | 30 | 35 | 65 | | 1 | 2012 | 50 | 40 | 90 | | 2 | 2012 | 28 | 0 | 28 | | 2 | 2012 | 38 | 0 | 38 | | 2 | 2012 | 48 | 0 | 48 |