一直在找一個比較參數化的 行轉列算法 (一個老話題了)今天看到一篇文章比較全面的介紹了的應用。算法
樣本數據如圖:sql
方法一:使用拼接SQL,靜態列字段;spa
方法二:使用拼接SQL,動態列字段;code
方法三:使用PIVOT關係運算符,靜態列字段;數學
方法四:使用PIVOT關係運算符,動態列字段;table
方法一:class
SELECT [UserName], SUM(CASE [Subject] WHEN '數學' THEN [Source] ELSE 0 END) AS '[數學]', SUM(CASE [Subject] WHEN '英語' THEN [Source] ELSE 0 END) AS '[英語]', SUM(CASE [Subject] WHEN '語文' THEN [Source] ELSE 0 END) AS '[語文]' FROM [TestRows2Columns] GROUP BY [UserName] GO
結果:進階
方法二:方法
DECLARE @sql VARCHAR(8000) SET @sql = 'SELECT [UserName],' SELECT @sql = @sql + 'SUM(CASE [Subject] WHEN '''+[Subject]+''' THEN [Source] ELSE 0 END) AS '''+QUOTENAME([Subject])+''',' FROM (SELECT DISTINCT [Subject] FROM [TestRows2Columns]) AS a SELECT @sql = LEFT(@sql,LEN(@sql)-1) + ' FROM [TestRows2Columns] GROUP BY [UserName]' PRINT(@sql) EXEC(@sql) GO
方法三:im
SELECT * FROM ( SELECT [UserName] , [Subject] , [Source] FROM [TestRows2Columns] ) p PIVOT ( SUM([Source]) FOR [Subject] IN ( [數學],[英語],[語文] ) ) AS pvt ORDER BY pvt.[UserName]; GO
方法四:各類必要的表名、分組列、行轉列字段、字段值都已經參數化,直接修改就行 做者:<聽風吹雨>
DECLARE @sql_str NVARCHAR(MAX) DECLARE @sql_col NVARCHAR(MAX) DECLARE @tableName SYSNAME --行轉列表 DECLARE @groupColumn SYSNAME --分組字段 DECLARE @row2column SYSNAME --行變列的字段 DECLARE @row2columnValue SYSNAME --行變列值的字段 SET @tableName = 'TestRows2Columns' SET @groupColumn = 'UserName' SET @row2column = 'Subject' SET @row2columnValue = 'Source' --從行數據中獲取可能存在的列 SET @sql_str = N' SELECT @sql_col_out = ISNULL(@sql_col_out + '','','''') + QUOTENAME(['+@row2column+']) FROM ['+@tableName+'] GROUP BY ['+@row2column+']' --PRINT @sql_str EXEC sp_executesql @sql_str,N'@sql_col_out NVARCHAR(MAX) OUTPUT',@sql_col_out=@sql_col OUTPUT --PRINT @sql_col SET @sql_str = N' SELECT * FROM ( SELECT ['+@groupColumn+'],['+@row2column+'],['+@row2columnValue+'] FROM ['+@tableName+']) p PIVOT (SUM(['+@row2columnValue+']) FOR ['+@row2column+'] IN ( '+ @sql_col +') ) AS pvt ORDER BY pvt.['+@groupColumn+']' --PRINT (@sql_str) EXEC (@sql_str)
各參數的說明入下圖:
這個方法還有一個進階版就是加入了查詢條件:
DECLARE @sql_str NVARCHAR(MAX) DECLARE @sql_col NVARCHAR(MAX) DECLARE @sql_where NVARCHAR(MAX) DECLARE @tableName SYSNAME --行轉列表 DECLARE @groupColumn SYSNAME --分組字段 DECLARE @row2column SYSNAME --行變列的字段 DECLARE @row2columnValue SYSNAME --行變列值的字段 SET @tableName = 'TestRows2Columns' SET @groupColumn = 'UserName' SET @row2column = 'Subject' SET @row2columnValue = 'Source' SET @sql_where = 'WHERE UserName = ''王五''' --過濾條件 --從行數據中獲取可能存在的列 SET @sql_str = N' SELECT @sql_col_out = ISNULL(@sql_col_out + '','','''') + QUOTENAME(['+@row2column+']) FROM ['+@tableName+'] '+@sql_where+' GROUP BY ['+@row2column+']' --PRINT @sql_str EXEC sp_executesql @sql_str,N'@sql_col_out NVARCHAR(MAX) OUTPUT',@sql_col_out=@sql_col OUTPUT --PRINT @sql_col SET @sql_str = N' SELECT * FROM ( SELECT ['+@groupColumn+'],['+@row2column+'],['+@row2columnValue+'] FROM ['+@tableName+']'+@sql_where+') p PIVOT (SUM(['+@row2columnValue+']) FOR ['+@row2column+'] IN ( '+ @sql_col +') ) AS pvt ORDER BY pvt.['+@groupColumn+']' --PRINT (@sql_str) EXEC (@sql_str)
結果如圖:
部份內容源自於聽風吹雨