You can do this without pivot (the syntax for which I find also complicated). Since you do not know the actual arrangement of the columns in advance, I think this is easiest with dynamic SQL. Given the following table / sample data:
USE tempdb; GO CREATE TABLE dbo.foo ( ItemID INT, MonthAsInt INT, [Month] VARCHAR(12), [Year] INT, InvType VARCHAR(12), Quantity INT ); INSERT dbo.foo SELECT 4643,4 ,'April ',2011,'Shipment',10 UNION ALL SELECT 4643,5 ,'May ',2011,'Shipment',10 UNION ALL SELECT 4643,7 ,'July ',2011,'Shipment',10 UNION ALL SELECT 4643,8 ,'August ',2011,'Destroy ',10 UNION ALL SELECT 4643,11,'November',2011,'Shipment',25 UNION ALL SELECT 4643,12,'December',2011,'Picking ',1;
You can create a list of months using the much simpler CTE and build on the basis of this dynamic SQL expression:
DECLARE @sql NVARCHAR(MAX) = N''; ;WITH n AS ( SELECT TOP (12) d = DATEADD ( MONTH, -(ROW_NUMBER() OVER (ORDER BY [object_id]) - 1), GETDATE() ) FROM sys.objects ORDER BY d DESC ) SELECT @sql = @sql + N',' + CHAR(13) + CHAR(10) + DATENAME(MONTH, d) + ' = SUM(CASE WHEN [Year] = ' + CONVERT(VARCHAR(4), DATEPART(YEAR, d)) + ' AND MonthAsInt = ' + CONVERT(VARCHAR(2), DATEPART(MONTH, d)) + ' THEN Quantity ELSE 0 END)' FROM n ORDER BY d; SELECT @sql = N'SELECT InvType' + @sql + ' FROM dbo.foo GROUP BY InvType'; PRINT @sql;
I put the PRINT there so you can check it out before running it. I was not sure if you need 12 months or 13 months, you can simply change TOP (12) to TOP (13) if you want 13 months, or delete -1 if you do not want the current month to be included.