MS SQL Server 行轉列的總結

一直在找一個比較參數化的 行轉列算法 (一個老話題了)今天看到一篇文章比較全面的介紹了的應用。算法

樣本數據如圖: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)

結果如圖:

 

部份內容源自於聽風吹雨

相關文章
相關標籤/搜索