设为首页 收藏本站
查看: 1399|回复: 0

[经验分享] 转:MSSQL SERVER行转列 列转行

[复制链接]

尚未签到

发表于 2017-12-14 18:17:21 | 显示全部楼层 |阅读模式
SQL Server中行列转换 Pivot UnPivot  
PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现
  

  
PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P
  

  
完整语法:
  

  
table_source
  

  
PIVOT(
  

  
聚合函数(value_column)
  

  
FOR pivot_column
  

  
IN(<column_list>)
  

  
)
  

  

  
UNPIVOT用于将列明转为列值(即列转行),在SQL Server 2000可以用UNION来实现
  

  
完整语法:
  

  
table_source
  

  
UNPIVOT(
  

  
value_column
  

  
FOR pivot_column
  

  
IN(<column_list>)
  

  
)
  

  

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

  

  
典型实例
  

  
一、行转列
  

  
1、建立表格
  

  
ifobject_id('tb')isnotnulldroptabletb
  

  
go
  

  
createtabletb(姓名varchar(10),课程varchar(10),分数int)
  

  
insertintotbvalues('张三','语文',74)
  

  
insertintotbvalues('张三','数学',83)
  

  
insertintotbvalues('张三','物理',93)
  

  
insertintotbvalues('李四','语文',74)
  

  
insertintotbvalues('李四','数学',84)
  

  
insertintotbvalues('李四','物理',94)
  

  
go
  

  
select*fromtb
  

  
go
  

  
姓名       课程       分数
  

  
---------- ---------- -----------
  

  
张三       语文        74
  

  
张三       数学        83
  

  
张三       物理        93
  

  
李四       语文        74
  

  
李四       数学        84
  

  
李四       物理        94
  

  

  
2、使用SQL Server 2000静态SQL
  

  
--c
  

  
select姓名,
  

  max(case课程when'语文'then分数else0end)语文,
  

  max(case课程when'数学'then分数else0end)数学,
  

  max(case课程when'物理'then分数else0end)物理
  

  
fromtb
  

  
groupby姓名
  

  
姓名       语文        数学        物理
  

  
---------- ----------- ----------- -----------
  

  
李四        74          84          94
  

  
张三        74          83          93
  

  

  
3、使用SQL Server 2000动态SQL
  

  
--SQL SERVER 2000动态SQL,指课程不止语文、数学、物理这三门课程。(以下同)
  

  
--变量按sql语言顺序赋值
  

  
declare@sqlvarchar(500)
  

  
set@sql='select姓名'
  

  
select@sql=@sql+',max(case课程when '''+课程+''' then分数else 0 end)['+课程+']'
  

  
from(selectdistinct课程fromtb)a--同from tb group by课程,默认按课程名排序
  

  
set@sql=@sql+' from tb group by姓名'
  

  
exec(@sql)
  

  

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

  
declare@sqlvarchar(8000)
  

  
select@sql=isnull(@sql+',','')+' max(case课程when '''+课程+''' then分数else 0 end) ['+课程+']'
  

  
from(selectdistinct课程fromtb)asa      
  

  
set@sql='select姓名,'+@sql+' from tb group by姓名'
  

  
exec(@sql)
  

  
姓名       数学        物理        语文
  

  
---------- ----------- ----------- -----------
  

  
李四        84          94          74
  

  
张三        83          93          74
  

  

  
4、使用SQL Server 2005静态SQL
  

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

  

  
5、使用SQL Server 2005动态SQL
  

  
--使用stuff()
  

  
declare@sqlvarchar(8000)
  

  
set@sql=''  --初始化变量@sql
  

  
select@sql=@sql+','+课程fromtbgroupby课程--变量多值赋值
  

  
set@sql=stuff(@sql,1,1,'')--去掉首个','
  

  
set@sql='select * from tb pivot (max(分数) for课程in ('+@sql+'))a'
  

  
exec(@sql)
  

  

  
--或使用isnull()
  

  
declare@sqlvarchar(8000)
  

  
–-获得课程集合
  

  
select@sql=isnull(@sql+',','')+课程fromtbgroupby课程           
  

  
set@sql='select * from tb pivot (max(分数) for课程in ('+@sql+'))a'
  

  
exec(@sql)
  

  

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

  
1、使用SQL Server 2000静态SQL
  

  
--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姓名
  

  
姓名       语文        数学        物理        总分        平均分
  

  
---------- ----------- ----------- ----------- -----------
  

  
李四        74          84          94          252         84.00
  

  
张三        74          83          93          250         83.33
  

  

  
2、使用SQL Server 2000动态SQL
  

  
--SQL SERVER 2000动态SQL
  

  
declare@sqlvarchar(500)
  

  
set@sql='select姓名'
  

  
select@sql=@sql+',max(case课程when '''+课程+''' then分数else 0 end)['+课程+']'
  

  
from(selectdistinct课程fromtb)a
  

  
set@sql=@sql+',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
  

  
--使用stuff()
  

  
--
  

  
declare@sqlvarchar(8000)
  

  
set@sql=''  --初始化变量@sql
  

  
select@sql=@sql+','+课程fromtbgroupby课程--变量多值赋值
  

  
--同select @sql = @sql + ','+课程from (select distinct课程from tb)a
  

  
set@sql=stuff(@sql,1,1,'')--去掉首个','
  

  
set@sql='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)
  

  

  
--或使用isnull()
  

  
declare@sqlvarchar(8000)
  

  
select@sql=isnull(@sql+',','')+课程fromtbgroupby课程
  

  
set@sql='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
  

  
go
  

  
姓名       语文        数学        物理
  

  
---------- ----------- ----------- -----------
  

  
张三       74          83          93
  

  
李四        74          84          94
  

  

  
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
  

  
姓名       课程 分数
  

  
---------- ---- -----------
  

  
李四       语文 74
  

  
李四       数学 84
  

  
李四       物理 94
  

  
张三       语文 74
  

  
张三       数学 83
  

  
张三       物理 93
  

  

  
2、使用SQL Server 2000动态SQL
  

  
--SQL SERVER 2000动态SQL。
  

  
--调用系统表动态生态。
  

  
declare@sqlvarchar(8000)
  

  
select@sql=isnull(@sql+' union all ','')+' select姓名, [课程]='
  

  
+quotename(Name,'''')+' , [分数] = '+quotename(Name)+' from tb'
  

  
fromsyscolumns
  

  
whereName!='姓名'andID=object_id('tb')--表名tb,不包含列名为姓名的其他列
  

  
orderbycolid
  

  
exec(@sql+' order by姓名')
  

  
go
  

  

  
3、使用SQL Server 2005静态SQL
  

  
--SQL SERVER 2005动态SQL
  

  
select姓名,课程,分数fromtb unpivot (分数for课程in([语文],[数学],[物理])) t
  

  

  
4、使用SQL Server 2005动态SQL
  

  
--SQL SERVER 2005动态SQL
  

  
declare@sqlnvarchar(4000)
  

  
select@sql=isnull(@sql+',','')+quotename(Name)
  

  
fromsyscolumns
  

  
whereID=object_id('tb')andNamenotin('姓名')
  

  
orderbyColid
  

  
set@sql='select姓名,[课程],[分数] from tb unpivot ([分数] for [课程] in('+@sql+'))b'
  

  
exec(@sql)
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-424112-1-1.html 上篇帖子: ASP.NET Core中的OWASP Top 10 十大风险 下篇帖子: C#实现SQL数据库备份与恢复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表