I worked up a dynamic version of this. Here's how I did it:1. Built a list of column names in a variable to use later:declare @colnames varchar(max) = ( select stuff(x, 1, 2, '') from ( select ', ' + QUOTENAME(part) from (select distinct part from #orders) q(part) order by part for xml path('') ) x(x))select @colnames
2. Built dynamic sql using the list above to build the pivot tabledeclare @sql varchar(max) = ' select ordernum, ' + @colnames + ' into ##pivoted from #orders pivot (count(part) for part in (' + @colnames + '))pvt'select @sqldrop table ##pivotedexec (@sql)select * from ##pivoted
3. Built a part names table (with ids) to build a @partsum variable:declare @parts table(partId int identity(0,1), part varchar(50))insert into @parts(part)select distinct part from #ordersselect * from @partsdeclare @partsum varchar(max) = ( select stuff(x, 1, 2, '') from ( select ', SUM(q.' + QUOTENAME(part) + ') ' + QUOTENAME(part) from @parts order by part for xml path('') ) x(x))select @partsum
4. Built a query to do one row of the matrix:declare @sql1 varchar(max) = ' select ' + @partsum + ', ''{col}'' part from ##pivoted p cross apply (select ' + @colnames + ' from ##pivoted where ordernum = p.ordernum and {col} > 0) q'select @sql1
5. Built the main query with all the unions in it:declare @sql2 varchar(max) = (select replace(@sql1, '{col}', QUOTENAME(part)) + ' union all'from @parts pjoin spt_values n on p.partId = n.numberwhere n.[type] = 'P'for xml path(''))set @sql2 = replace(replace(@sql2, '#x0D;', ''), '>', '>')set @sql2 = 'select * from ('+ substring(@sql2, 1, len(@sql2)-9) + ') qorder by part'select @sql2
6. Executed the main query:exec (@sql2)