I tend to steer clear of dynamic SQL if I can. Apart from the possible security implecations if the execution is exposed to the outside world the dynamic queries don't benefit from stored optimisation etc.If it is only the pivot headers you want to be dynamic and you can apply column headers at the interface layer then this peice of test code may give you some ideas. Oh, assuming that the actuall number of columns is fixed of course.I have included the whole test shebang. I actually find it really useful to store create and store example queries like this for re-use later:/*** Semi Flexible Pivot Example**/DECLARE @currentYear intDECLARE @yearsBack intDECLARE @myData TABLE (myID int, myDate datetime, myVal int)DECLARE @counter intSET @currentYear = YEAR(GETDATE())SET @counter = 10WHILE @counter > -1BEGIN INSERT @myData SELECT 1, '01 Jan ' + CAST(YEAR(GETDATE()) - @counter AS VARCHAR), YEAR(GETDATE()) - @counter + 10000 UNION SELECT 2, '01 Jan ' + CAST(YEAR(GETDATE()) - @counter AS VARCHAR), YEAR(GETDATE()) - @counter + 20000 UNION SELECT 1, '01 Feb ' + CAST(YEAR(GETDATE()) - @counter AS VARCHAR), YEAR(GETDATE()) - @counter + 10000 UNION SELECT 2, '01 Feb ' + CAST(YEAR(GETDATE()) - @counter AS VARCHAR), YEAR(GETDATE()) - @counter + 20000 SET @counter = @counter - 1ENDSELECT myID, [10],[9],
,[7],[6],[5],[4],[3],[2],[1]FROM ( SELECT myID, myVal, NTILE(10) OVER(PARTITION BY MyID ORDER BY YEAR(myDate) DESC) AS yearOffset FROM @myData ) ma PIVOT ( sum(MyVal) FOR [yearOffset] IN ([10],[9],
,[7],[6],[5],[4],[3],[2],[1]) ) p