1 CREATE PROCEDURE [dbo].[p_Pivot_WithSum_VH](@tabName nvarchar(MAX),@rowName nvarchar(MAX),@colName nvarchar(MAX), 2 @numName nvarchar(MAX),@calcMethod nvarchar(MAX)) 3 AS 4 BEGIN 5 -- SET NOCOUNT ON added to prevent extra result sets from 6 -- interfering with SELECT statements. 7 SET NOCOUNT ON; 8 9 -- Insert statements for procedure here 10 11 -- Compared with the sp [p_Pivot] or [p_Pivot_WithSum], this sp adds the subtotal line for both rows and columns. 12 -- Especially, this sp processes the name shown in the returned table as [*] if it's a string field, and [blank] if time/number/etc. 13 14 15 DECLARE @sql nvarchar(MAX),@col nvarchar(MAX),@sql_col nvarchar(MAX) 16 17 SELECT @sql_col=N'SELECT @col_out=ISNULL(@col_out+'','','''')+QUOTENAME(['+@colName+']) FROM ['+@tabName 18 +'] GROUP BY ['+@colName+'] ORDER BY ['+@colName+']' 19 EXEC SP_EXECUTESQL @sql_col,N'@col_out nvarchar(MAX) OUTPUT',@col_out=@col OUTPUT 20 21 22 declare @rowList nvarchar(max),@row_first nvarchar(100),@row_last nvarchar(100),@rowRank nvarchar(max) 23 if @rowName like '%,%' 24 begin 25 select @row_first=left(@rowName,charindex(',',@rowName)-1) 26 select @row_last=right(@rowName,charindex(',',reverse(@rowName))-1) 27 end 28 else 29 select @row_first=@rowName,@row_last=@rowName 30 31 select @rowList=isnull(@rowList+' and ','')+'t1.'+ElementOutput+'=t2.'+ElementOutput from dbo.StringToList(@rowName,',') 32 select @rowRank=isnull(@rowRank+',','')+'t1.'+ElementOutput from dbo.StringToList(@rowName,',') 33 34 35 declare @rep_value table(Field nvarchar(max),FType nvarchar(100),FTypeId int) 36 declare @ttl nvarchar(max)=','+@rowName+',',@sInput nvarchar(100),@sOutput nvarchar(100) 37 38 if @tabName like '%#%' 39 begin 40 insert into @rep_value 41 select t2.ElementOutput,case when xtype in (167,175,231,239) then '''*''' else 'null' end TotalInfo,xtype from ( 42 select * from tempdb..syscolumns where id=OBJECT_ID('tempdb..'+@tabName)) t1 full join dbo.StringToList(@rowName,',') t2 on t1.name=t2.ElementOutput 43 end 44 else 45 begin 46 insert into @rep_value 47 select t2.ElementOutput,case when xtype in (167,175,231,239) then '''*''' else 'null' end TotalInfo,xtype from ( 48 select * from syscolumns where id=OBJECT_ID(@tabName)) t1 full join dbo.StringToList(@rowName,',') t2 on t1.name=t2.ElementOutput 49 end 50 51 while exists(select * from @rep_value where @ttl like '%,'+Field+',%') 52 begin 53 select @sInput=','+Field+',',@sOutput=','+FType+',' from @rep_value where @ttl like '%,'+Field+',%' 54 select @ttl=replace(@ttl,@sInput,@sOutput) 55 end 56 57 select @ttl=SUBSTRING(@ttl,2,len(@ttl)-2) 58 59 IF @rowName IS NULL 60 SELECT @sql=N'SELECT '''+@numName+''' AS ['+@colName+'],* FROM (SELECT ['+@colName+'],['+@numName+'] FROM ['+@tabName+']) t 61 PIVOT('+@calcMethod+'(['+@numName+']) FOR ['+@colName+'] IN ('+@col+')) p' 62 ELSE 63 SELECT @sql=N'SELECT t1.*,t2.[*] FROM (SELECT *,0 AS SubtotalRow FROM ( 64 65 SELECT '+@rowName+',['+@colName+'],['+@numName+'] FROM ['+@tabName+']) t 66 PIVOT('+@calcMethod+'(['+@numName+']) FOR ['+@colName+'] IN ('+@col+')) p 67 UNION 68 SELECT '+@ttl+',*,1 FROM (SELECT '+@colName+','+@calcMethod+'('+@numName+') AS I FROM '+@tabName+' GROUP BY '+@colName+ 69 ') t PIVOT(SUM([I]) FOR ['+@colName+'] IN ('+@col+')) p 70 71 ) t1 left join ( 72 select grouping(['+@row_first+']) SubtotalRow,'+@rowName+',['+@colName+'],'+@calcMethod+'(['+@numName+']) [*] from ['+@tabName+'] group by '+@rowName+',['+@colName+'] with rollup having grouping(['+@colName+'])=1 and (['+@row_first+'] is null or ['+@row_last+'] is not null) 73 ) t2 on '+@rowList+' or t1.SubtotalRow=1 and t2.SubtotalRow=1 74 75 ORDER BY t1.SubtotalRow,'+@rowRank 76 PRINT @sql 77 EXEC SP_EXECUTESQL @sql 78 79 80 END