SQL数据透视表与总计行/列的实现

在数据库管理与分析中,数据透视表是一种常用的数据汇总方法,它能够将行数据转换成列数据,从而实现数据的聚合展示。SQL Server 2005引入了PIVOT操作,使得在SQL中实现数据透视表变得简单。本文将探讨如何在SQL中使用PIVOT和UNPIVOT操作,并重点介绍如何添加总计行和列。

作为一名.NET开发者,通常会从存储过程获取数据透视表,并在C#/VB代码中使用Datatable来计算总计行和列。但本文将展示如何在存储过程中直接获取这些总计,以便在不进行任何C#/VB代码操作的情况下直接在网格中显示数据。

PIVOT和UNPIVOT操作

PIVOT操作可以将表值表达式中的一列的唯一值转换为输出中的多个列,并在需要的地方对任何剩余的列值进行聚合。相反,UNPIVOT操作将表值表达式的列转换为列值。

动态SQL与数据透视表

在实际应用中,经常需要动态地生成PIVOT操作中的列列表。以下是一个简单的SQL脚本,展示了如何动态生成PIVOT操作的列列表: DECLARE @cols NVARCHAR(MAX) SELECT @cols = COALESCE(@cols + ', [' + colName + ']', '[' + colName + ']') FROM Table1 WHERE Conditions ORDER BY colName PRINT @cols

创建存储过程

以下SQL脚本创建了一个存储过程,该过程返回数据透视表作为输出: CREATE PROCEDURE pivot_TeamVsMatches AS DECLARE @columnHeaders NVARCHAR(MAX) SELECT @columnHeaders = COALESCE(@columnHeaders + ', [' + month + ']', '[' + month + ']') FROM tbl_Matches ORDER BY month DECLARE @FinalQuery NVARCHAR(MAX) SET @FinalQuery = 'SELECT * FROM (SELECT Team, Month FROM tbl_Matches) A PIVOT ( COUNT(*) FOR ColName IN (' + @columnHeaders + ')) B ORDER BY Team' PRINT 'Pivot Query :' + @FinalQuery EXECUTE (@FinalQuery) GO

添加总计行和列

为了在数据透视表中添加总计行和列,需要构建COALESCE查询。以下是生成总计列的SQL脚本: DECLARE @GrandTotalCol NVARCHAR(MAX) SELECT @GrandTotalCol = COALESCE(@GrandTotalCol + ' + ISNULL([' + CAST(Month AS VARCHAR) + '], 0)', 'ISNULL([' + CAST(Month AS VARCHAR) + '], 0)') FROM tbl_Matches GROUP BY Month ORDER BY Month SET @GrandTotalCol = LEFT(@GrandTotalCol, LEN(@GrandTotalCol)-1)

以下是生成总计行的SQL脚本: DECLARE @GrandTotalRow NVARCHAR(MAX) SELECT @GrandTotalRow = COALESCE(@GrandTotalRow + ', ISNULL(SUM([' + CAST(Month AS VARCHAR) + '])', 0)', 'ISNULL(SUM([' + CAST(Month AS VARCHAR) + '])', 0)') FROM tbl_Matches GROUP BY Month ORDER BY Month

完整的存储过程

以下是完整的存储过程,它将生成包含总计行和列的数据透视表: CREATE PROCEDURE pivot_TeamVsMatches AS DECLARE @columnHeaders NVARCHAR(MAX) SELECT @columnHeaders = COALESCE(@columnHeaders + ', [' + month + ']', '[' + month + ']') FROM tbl_Matches GROUP BY month ORDER BY month DECLARE @GrandTotalCol NVARCHAR(MAX) SELECT @GrandTotalCol = COALESCE(@GrandTotalCol + ' + ISNULL([' + CAST(Month AS VARCHAR) + '], 0)', 'ISNULL([' + CAST(Month AS VARCHAR) + '], 0)') FROM tbl_Matches GROUP BY Month ORDER BY Month SET @GrandTotalCol = LEFT(@GrandTotalCol, LEN(@GrandTotalCol)-1) DECLARE @GrandTotalRow NVARCHAR(MAX) SELECT @GrandTotalRow = COALESCE(@GrandTotalRow + ', ISNULL(SUM([' + CAST(Month AS VARCHAR) + '])', 0)', 'ISNULL(SUM([' + CAST(Month AS VARCHAR) + '])', 0)') FROM tbl_Matches GROUP BY Month ORDER BY Month DECLARE @FinalQuery NVARCHAR(MAX) SET @FinalQuery = 'SELECT *, (' + @GrandTotalCol + ') AS [Grand Total] INTO #temp_MatchesTotal FROM (SELECT Team, Month FROM tbl_Matches) A PIVOT ( COUNT(*) FOR ColName IN (' + @columnHeaders + ')) B ORDER BY Team SELECT * FROM #temp_MatchesTotal UNION ALL SELECT ''Grand Total'', '''', ' + @GrandTotalRow + ', ISNULL(SUM([Grand Total]),0) FROM #temp_MatchesTotal DROP TABLE #temp_MatchesTotal' PRINT 'Pivot Query ' + @FinalQuery EXECUTE (@FinalQuery) GO

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485