SQL SERVER 行转列 (转载)

 

(1)首先创建测试表

复制代码
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TestRows2Columns]') AND type in (N'U'))
DROP TABLE [dbo].[TestRows2Columns]
GO
CREATE TABLE [dbo].[TestRows2Columns](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [UserName] [nvarchar](50) NULL,
    [Subject] [nvarchar](50) NULL,
    [Source] [numeric](18, 0) NULL
) ON [PRIMARY]
GO

--插入测试数据
INSERT INTO [TestRows2Columns] ([UserName],[Subject],[Source]) 
    SELECT N'张三',N'语文',60  UNION ALL
    SELECT N'李四',N'数学',70  UNION ALL
    SELECT N'王五',N'英语',80  UNION ALL
    SELECT N'王五',N'数学',75  UNION ALL
    SELECT N'王五',N'语文',57  UNION ALL
    SELECT N'李四',N'语文',80  UNION ALL
    SELECT N'张三',N'英语',100
GO
复制代码

(2)静态行转列 

select username ,
MAX(case SubJect when '语文' then source else 0 end ) as '语文',
MAX(case SubJect when '数学' then source else 0 end ) as '数学',
MAX(case SubJect when '英语' then source else 0 end ) as '英语'

from [TestRows2Columns] group by username

结果:

 

(3)QUOTENAME() 函数主要是确保参数成为有效的标识符,比如下面Subject的值如果是:数学 洒水,中间存在空格,这时候就会出现异常,所以使用QUOTENAME就会
将其变为有效标识符

复制代码
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) --可以打印出来看看具体SQL
EXEC(@sql)  --执行
GO
复制代码

 

 (4)还可以使用PIVOT关系运算符来进行行转列  静态

复制代码
SELECT  *
FROM    ( SELECT    [UserName] ,
                    [Subject] ,
                    [Source]
          FROM      [TestRows2Columns]
        ) p PIVOT
( SUM([Source]) FOR [Subject] IN ( [数学],[英语],[语文] ) ) AS pvt
ORDER BY pvt.[UserName];
GO
复制代码

(5)动态行转列

 

复制代码
DECLARE @sql_str VARCHAR(8000)
DECLARE @sql_col VARCHAR(8000)
SELECT @sql_col = ISNULL(@sql_col+',','') + QUOTENAME([Subject]) FROM [TestRows2Columns] GROUP BY [Subject]  
SET @sql_str = '
SELECT * FROM (
    SELECT [UserName],[Subject],[Source] FROM [TestRows2Columns]) p PIVOT 
    (SUM([Source]) FOR [Subject] IN ( '+ @sql_col +') ) AS pvt 
ORDER BY pvt.[UserName]'
PRINT (@sql_str)
EXEC (@sql_str)
复制代码

 

(6)带条件查询的参数化动态PIVOT行转列

复制代码
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)
复制代码

 

posted @   安静点--  阅读(1029)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
历史上的今天:
2020-07-06 c#之线程同步
点击右上角即可分享
微信分享提示