Search code examples
sqlsql-serverpivotsql-server-2016subtotal

Add Total column to Dynamic SQL pivot


Lots of these types of questions out there, but unable to find anything that matches what I am looking for.

I am using code from another post that is working great, but I would like to modify it to add a totals row at the bottom of the table.

The previous post so the creator gets credit is: SQL Server dynamic pivot with multiple columns

My current table looks like:

Work_Group Avg 01/01/2021 01/01/2021 01/01/2021 ect...
Blue 5 2 5 8
Green 5 2 5 8

Goal:

Work_Group Avg 01/01/2021 01/01/2021 01/01/2021 ect...
Blue 5 2 5 8
Green 5 2 5 8
TOTAL 10 4 10 16

Current Code is:

DECLARE @colsEAST AS NVARCHAR(MAX);
DECLARE @pivotCountEAST AS NVARCHAR(MAX);
DECLARE @sqlEAST AS NVARCHAR(MAX);

SELECT @colsEAST = ISNULL(@colsEAST + ', ', '') + QUOTENAME(Load_Date)
FROM (SELECT DISTINCT Load_Date FROM ##CE_tmpEast_ALL) AS Load_Date

SET @pivotCountEAST = N'SELECT Work_Group, ' + @colsEAST +'
FROM (SELECT Work_Group, Load_Date, Count FROM ##CEtmp_East_ALL) AS Count
PIVOT(SUM(Count) FOR Load_Date IN (' + @colsEAST + ')) AS pvt';

SET @sqlEAST = '; WITH MTD_CountPivot AS (
'+@pivotCountEAST+'
),

MTD_Pivot_Tables AS (
  SELECT Work_Group, AVG(Count) AS [AVG Count]
  FROM ##CEtmp_East_ALL
  GROUP BY Work_Group
)
SELECT MTD_CountPivot.Work_Group,  MTD_Pivot_Tables.[AVG Count], ' + @colsEAST + '
FROM
MTD_CountPivot

INNER JOIN MTD_Pivot_Tables ON MTD_CountPivot.Work_Group = MTD_Pivot_Tables.Work_Group';

EXEC sp_executesql @sqlEAST;

Any help would be greatly appreciated!!!

Thank you


Solution

  • You can add GROUPING SETS ((mcp.Work_Group),()) to the current query in order to get subtotals. For this, need to create another parameter @colsEAST2 in order to hold generated list of the dates for column headers as

    SUM([2001-01-01]) AS [2001-01-01],SUM([2001-01-02]) AS [2001-01-02],SUM([2001-01-03]) AS [2001-01-03]

    along with @colsEAST which holds

    [2001-01-01],[2001-01-02],[2001-01-03]

    DECLARE @colsEAST       AS NVARCHAR(MAX);
    DECLARE @colsEAST2      AS NVARCHAR(MAX);
    DECLARE @pivotCountEAST AS NVARCHAR(MAX);
    DECLARE @sqlEAST        AS NVARCHAR(MAX);
    
    SELECT @colsEAST = ISNULL(@colsEAST + ', ', '') + QUOTENAME(Load_Date)
      FROM (SELECT DISTINCT Load_Date 
              FROM ##CE_tmpEast_ALL) AS Load_Date;    
    SELECT @colsEAST2 = ISNULL(@colsEAST2 + ', ', '') 
                    + ' SUM('+QUOTENAME(Load_Date)+') AS '+QUOTENAME(Load_Date)
      FROM (SELECT DISTINCT Load_Date 
              FROM ##CE_tmpEast_ALL) AS Load_Date;    
    SET @pivotCountEAST = N'SELECT Work_Group, ' + @colsEAST2 +'
                              FROM (SELECT Work_Group, Load_Date, Count 
                                      FROM ##CE_tmpEast_ALL) AS Count
                             PIVOT(SUM(Count) FOR Load_Date IN (' + @colsEAST + ')) AS pvt
                             GROUP BY Work_Group';                             
    SET @sqlEAST = '; WITH MTD_CountPivot AS (
    '+@pivotCountEAST+'
    ), MTD_Pivot_Tables AS (
      SELECT Work_Group, AVG(Count) AS [AVG Count]
        FROM ##CE_tmpEast_ALL
       GROUP BY Work_Group
    )
    SELECT CASE WHEN GROUPING(mcp.Work_Group) = 0 
                THEN mcp.Work_Group 
                ELSE ''TOTAL'' 
                 END AS Work_Group,
           SUM(mpt.[AVG Count]) AS Avg, 
           ' + @colsEAST2+ '
      FROM MTD_CountPivot mcp
      JOIN MTD_Pivot_Tables mpt 
        ON mcp.Work_Group = mpt.Work_Group
     GROUP BY GROUPING SETS ((mcp.Work_Group),())';    
    EXEC sp_executesql @sqlEAST;
    

    Demo