SqlServer行转列(PIVOT),列转行(UNPIVOT)总结

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SqlServer行转列(PIVOT),列转行(UNPIVOT)总结相关的知识,希望对你有一定的参考价值。

PIVOT用于将列值旋转为列名(即行转列)

语法:

table_source
PIVOT(
聚合函数(value_column)
FOR pivot_column
IN(<column_list>)
)

 UNPIVOT用于将列明转为列值(即列转行)

语法:

table_source
UNPIVOT(
value_column
FOR pivot_column
IN(<column_list>)
)

注意:PIVOT、UNPIVOT是SQL Server 2005的语法,使用需修改数据库兼容级别
 在数据库属性->选项->兼容级别改为   90

一、行转列

1、建立表格

ifobject_id(‘tb‘)isnotnulldroptabletb
go
Create table tb(姓名 varchar(10),课程 varchar(10),分数 int)
Insert into tb values(‘张三‘,‘语文‘,74)
Insert into tb values(‘张三‘,‘数学‘,83)
Insert into tb values(‘张三‘,‘物理‘,93)
Insert into tb values(‘李四‘,‘语文‘,74)
Insert into tb values(‘李四‘,‘数学‘,84)
Insert into tb values(‘李四‘,‘物理‘,94)
go
Select * from tb

 

2、使用SQL Server 2000静态SQL

 select姓名,
 Max (case课程when‘语文‘then分数else 0 end)语文,
 Max (case课程when‘数学‘then分数else 0 end)数学,
 Max (case课程when‘物理‘then分数else 0 end)物理
From tb
Group by姓名

 

3、使用SQL Server 2000动态SQL

[email protected](500)
[email protected]=‘select姓名‘
[email protected][email protected]+‘,max(case课程when ‘‘‘+课程+‘‘‘ then分数else 0 end)[‘+课程+‘]‘
from(selectdistinct课程fromtb)a--同from tb group by课程,默认按课程名排序
[email protected][email protected]+‘ from tb group by姓名‘
exec(@sql)

 

--使用isnull(),变量先确定动态部分

[email protected](8000)
[email protected]=isnull(@sql+‘,‘,‘‘)+‘ max(case课程when ‘‘‘+课程+‘‘‘ then分数else 0 end) [‘+课程+‘]‘
from(selectdistinct课程fromtb)asa      
[email protected]=‘select姓名,‘[email protected]+‘ from tb group by姓名‘
exec(@sql)

 

4、使用SQL Server 2005静态SQL

select*fromtb pivot(max(分数)for课程in(语文,数学,物理))a

 

5、使用SQL Server 2005动态SQL

--使用stuff()
[email protected](8000)
[email protected]=‘‘  --初始化变量@sql
[email protected][email protected]+‘,‘+课程fromtbgroupby课程--变量多值赋值
[email protected]=stuff(@sql,1,1,‘‘)--去掉首个‘,‘
[email protected]=‘select * from tb pivot (max(分数) for课程in (‘[email protected]+‘))a‘
exec(@sql)
 
--或使用isnull()
[email protected](8000)
–-获得课程集合
[email protected]=isnull(@sql+‘,‘,‘‘)+课程fromtbgroupby课程           
[email protected]=‘select * from tb pivot (max(分数) for课程in (‘[email protected]+‘))a‘
exec(@sql)

 

二、行转列结果加上总分、平均分

1、使用SQL Server 2000静态SQL

select姓名,
max(case课程when‘语文‘then分数else0end)语文,
max(case课程when‘数学‘then分数else0end)数学,
max(case课程when‘物理‘then分数else0end)物理,
sum(分数)总分,
cast(avg(分数*1.0)asdecimal(18,2))平均分
fromtb
groupby姓名

 

2、使用SQL Server 2000动态SQL

--SQL SERVER 2000动态SQL
[email protected](500)
[email protected]=‘select姓名‘
[email protected][email protected]+‘,max(case课程when ‘‘‘+课程+‘‘‘ then分数else 0 end)[‘+课程+‘]‘
from(selectdistinct课程fromtb)a
[email protected][email protected]+‘,sum(分数)总分,cast(avg(分数*1.0) as decimal(18,2))      平均分from tb group by姓名‘
exec(@sql)

 

3、使用SQL Server 2005静态SQL

selectm.*,n.总分,n.平均分
from
(select*fromtb pivot(max(分数)for课程in(语文,数学,物理))a)m,
(select姓名,sum(分数)总分,cast(avg(分数*1.0)asdecimal(18,2))平均分
fromtb
groupby姓名)n
wherem.姓名=n.姓名
 

 

4、使用SQL Server 2005动态SQL

[email protected](8000)
[email protected]=‘‘  --初始化变量@sql
[email protected][email protected]+‘,‘+课程fromtbgroupby课程--变量多值赋值
--同select @sql = @sql + ‘,‘+课程from (select distinct课程from tb)a
[email protected]=stuff(@sql,1,1,‘‘)--去掉首个‘,‘
[email protected]=‘select m.* , n.总分,n.平均分from
(select * from (select * from tb) a pivot (max(分数) for课程in (‘[email protected]+‘)) b) m ,
(select姓名,sum(分数)总分, cast(avg(分数*1.0) as decimal(18,2))平均分from tb group by姓名) n
where m.姓名= n.姓名‘
exec(@sql)
 
--或使用isnull()
[email protected](8000)
[email protected]=isnull(@sql+‘,‘,‘‘)+课程fromtbgroupby课程
[email protected]=‘select m.* , n.总分,n.平均分from
(select * from (select * from tb) a pivot (max(分数) for课程in (‘+
 @sql+‘)) b) m ,
(select姓名,sum(分数)总分, cast(avg(分数*1.0) as decimal(18,2))平均分from tb group by姓名) n
where m.姓名= n.姓名‘
exec(@sql)

 

二、列转行

1、建立表格

ifobject_id(‘tb‘)isnotnulldroptabletb
go
createtabletb(姓名varchar(10),语文int,数学int,物理int)
insertintotbvalues(‘张三‘,74,83,93)
insertintotbvalues(‘李四‘,74,84,94)
go
select*fromtb

 

2、使用SQL Server 2000静态SQL

--SQL SERVER 2000静态SQL。
select*from
(
 select姓名,课程=‘语文‘,分数=语文fromtb
 unionall
 select姓名,课程=‘数学‘,分数=数学fromtb
 unionall
 select姓名,课程=‘物理‘,分数=物理fromtb
) t
orderby姓名,case课程when‘语文‘then1when‘数学‘then2when‘物理‘then3end

 

2、使用SQL Server 2000动态SQL

--SQL SERVER 2000动态SQL。
--调用系统表动态生态。
[email protected](8000)
[email protected]=isnull(@sql+‘ union all ‘,‘‘)+‘ select姓名, [课程]=‘
+quotename(Name,‘‘‘‘)+‘ , [分数] = ‘+quotename(Name)+‘ from tb‘
fromsyscolumns
whereName!=‘姓名‘andID=object_id(‘tb‘)--表名tb,不包含列名为姓名的其他列
orderbycolid
exec(@sql+‘ order by姓名‘)

 

3、使用SQL Server 2005静态SQL   

--SQL SERVER 2005动态SQL
select姓名,课程,分数fromtb unpivot (分数for课程in([语文],[数学],[物理])) t

 4、使用SQL Server 2005动态SQL

--SQL SERVER 2005动态SQL
[email protected](4000)
[email protected]=isnull(@sql+‘,‘,‘‘)+quotename(Name)
fromsyscolumns
whereID=object_id(‘tb‘)andNamenotin(‘姓名‘)
orderbyColid
[email protected]=‘select姓名,[课程],[分数] from tb unpivot ([分数] for [课程] in(‘[email protected]+‘))b‘
exec(@sql)

 

以上是关于SqlServer行转列(PIVOT),列转行(UNPIVOT)总结的主要内容,如果未能解决你的问题,请参考以下文章

死磕:SQL行转列汇总(全网最全最详细)

重温SQL——行转列,列转行

SqlServer基本操作

T-Sql语法:行转列(pivot)和列转行(unpivot)

sql的行转列(PIVOT)与列转行(UNPIVOT)

sql的行转列(PIVOT)与列转行(UNPIVOT)