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

[经验分享] SQL 2000,SQL2005 行列转换

[复制链接]

尚未签到

发表于 2016-11-8 08:54:12 | 显示全部楼层 |阅读模式
  PIVOT用于将列值旋转为列名(即行转列),在SQL Server2000可以用聚合函数配合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--fromtb group by课程,默认按课程名排序
  set@sql=@sql+' from tbgroup 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*fromtbpivot(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*fromtbpivot(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))平均分fromtb 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))平均分fromtb 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姓名,课程,分数fromtbunpivot (分数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)


该文章经过本人整理所得,欢迎转载,转载时请加上本文地址;本文基于署名 2.5 中国大陆许可协议发布,请勿演绎或用于商业目的,但是必须保留本文的署名张志涛(包含链接如您有任何疑问或者授权方面的协商,请给我留言

运维网声明 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-297189-1-1.html 上篇帖子: BizTalk Server 事务机制 下篇帖子: SQL SERVER性能优化综述(很好的总结,不要错过哦)第2/3页
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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