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