SQL行转列的一个例子

本文展示了如何使用SQL Server实现学生成绩的汇总与分析,包括静态和动态SQL查询,以及如何在查询结果中加入平均分和总分。同时,介绍了如何将表结构互换并进行相应的查询操作,并对结果进行了平均分和总分的计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. /* 
  2. 问题:假设有张学生成绩表(score)如下: 
  3. sname subject scores 
  4. 王刚 语文 75 
  5. 王刚 数学 83 
  6. 王刚 英语 93 
  7. 李军 语文 74 
  8. 李军 数学 84 
  9. 李军 英语 94 
  10. 想变成(得到如下结果):  
  11. sname 语文 数学 英语  
  12. ---- ---- ---- ---- 
  13. 李军 74   84   94 
  14. 王刚 75   83   93 
  15. ------------------- 
  16. */  
  17. create table tb(sname varchar(10) , subject varchar(10) , scores int)  
  18. insert into tb values('王刚' , '语文' , 75)  
  19. insert into tb values('王刚' , '数学' , 83)  
  20. insert into tb values('王刚' , '英语' , 93)  
  21. insert into tb values('李军' , '语文' , 74)  
  22. insert into tb values('李军' , '数学' , 84)  
  23. insert into tb values('李军' , '英语' , 94)  
  24. go  
  25. --SQL SERVER 2000 静态SQL,指subject只有语文、数学、英语这三门subject。(以下同)  
  26. select sname as sname ,  
  27.   max(case subject when '语文' then scores else 0 end) 语文,  
  28.   max(case subject when '数学' then scores else 0 end) 数学,  
  29.   max(case subject when '英语' then scores else 0 end) 英语  
  30. from tb  
  31. group by sname  
  32. --SQL SERVER 2000 动态SQL,指subject不止语文、数学、英语这三门subject。(以下同)  
  33. declare @sql varchar(8000)  
  34. set @sql = 'select sname '  
  35. select @sql = @sql + ' , max(case subject when ''' + subject + ''' then scores else 0 end) [' + subject + ']'  
  36. from (select distinct subject from tb) as a  
  37. set @sql = @sql + ' from tb group by sname'  
  38. exec(@sql)   
  39. --SQL SERVER 2005 静态SQL。  
  40. select * from tb a pivot (max(scores) for subject in (语文,数学,英语)) b  
  41. --SQL SERVER 2005 动态SQL。  
  42. declare @sql varchar(8000)  
  43. select @sql = isnull(@sql + '],[' , '') + subject from tb group by subject  
  44. set @sql = '[' + @sql + ']'  
  45. exec ('select * from (select * from tb) a pivot (max(scores) for subject in (' + @sql + ')) b')  
  46. ---------------------------------  
  47. /* 
  48. 问题:在上述结果的基础上加平均分,总分,得到如下结果: 
  49. sname 语文 数学 英语 平均分 总分  
  50. ---- ---- ---- ---- ------ ---- 
  51. 李军 74   84   94   84.00  252 
  52. 王刚 75   83   93   83.33  251 
  53. */  
  54. --SQL SERVER 2000 静态SQL。  
  55. select sname sname,  
  56.   max(case subject when '语文' then scores else 0 end) 语文,  
  57.   max(case subject when '数学' then scores else 0 end) 数学,  
  58.   max(case subject when '英语' then scores else 0 end) 英语,  
  59.   cast(avg(scores*1.0) as decimal(18,2)) 平均分,  
  60.   sum(scores) 总分  
  61. from tb  
  62. group by sname  
  63. --SQL SERVER 2000 动态SQL。  
  64. declare @sql varchar(8000)  
  65. set @sql = 'select sname '  
  66. select @sql = @sql + ' , max(case subject when ''' + subject + ''' then scores else 0 end) [' + subject + ']'  
  67. from (select distinct subject from tb) as a  
  68. set @sql = @sql + ' , cast(avg(scores*1.0) as decimal(18,2)) 平均分 , sum(scores) 总分 from tb group by sname'  
  69. exec(@sql)   
  70. --SQL SERVER 2005 静态SQL。  
  71. select m.* , n.平均分 , n.总分 from  
  72. (select * from (select * from tb) a pivot (max(scores) for subject in (语文,数学,英语)) b) m,  
  73. (select sname , cast(avg(scores*1.0) as decimal(18,2)) 平均分 , sum(scores) 总分 from tb group by sname) n  
  74. where m.sname = n.sname  
  75. --SQL SERVER 2005 动态SQL。  
  76. declare @sql varchar(8000)  
  77. select @sql = isnull(@sql + ',' , '') + subject from tb group by subject  
  78. exec ('select m.* , n.平均分 , n.总分 from  
  79. (select * from (select * from tb) a pivot (max(scores) for subject in (' + @sql + ')) b) m ,   
  80. (select sname , cast(avg(scores*1.0) as decimal(18,2)) 平均分 , sum(scores) 总分 from tb group by sname) n  
  81. where m.sname = n.sname')  
  82. drop table tb      
  83. ------------------  
  84. ------------------  
  85. /* 
  86. 问题:如果上述两表互相换一下:即表结构和数据为: 
  87. sname 语文 数学 英语 
  88. 王刚 75  83  93 
  89. 李军 74  84  94 
  90. 想变成(得到如下结果):  
  91. sname subject scores  
  92. ---- ---- ---- 
  93. 李军 语文 74 
  94. 李军 数学 84 
  95. 李军 英语 94 
  96. 王刚 语文 75 
  97. 王刚 数学 83 
  98. 王刚 英语 93 
  99. -------------- 
  100. */  
  101. create table tb(sname varchar(10) , 语文 int , 数学 int , 英语 int)  
  102. insert into tb values('王刚',75,83,93)  
  103. insert into tb values('李军',74,84,94)  
  104. go  
  105. --SQL SERVER 2000 静态SQL。  
  106. select * from  
  107. (  
  108.  select sname , subject = '语文' , scores = 语文 from tb   
  109.  union all  
  110.  select sname , subject = '数学' , scores = 数学 from tb  
  111.  union all  
  112.  select sname , subject = '英语' , scores = 英语 from tb  
  113. ) t  
  114. order by sname , case subject when '语文' then 1 when '数学' then 2 when '英语' then 3 end  
  115. --SQL SERVER 2000 动态SQL。  
  116. --调用系统表动态生态。  
  117. declare @sql varchar(8000)  
  118. select @sql = isnull(@sql + ' union all ' , '' ) + ' select sname , [subject] = ' + quotename(Name , '''') + ' , [scores] = ' + quotename(Name) + ' from tb'  
  119. from syscolumns   
  120. where name! = N'sname' and ID = object_id('tb') --表名tb,不包含列名为sname的其它列  
  121. order by colid asc  
  122. exec(@sql + ' order by sname ')  
  123. --SQL SERVER 2005 静态SQL。  
  124. select sname , subject , scores from tb unpivot (scores for subject in([语文] , [数学] , [英语])) t  
  125. --SQL SERVER 2005 动态SQL,同SQL SERVER 2000 动态SQL。  
  126. --------------------  
  127. /* 
  128. 问题:在上述的结果上加个平均分,总分,得到如下结果: 
  129. sname subject   scores 
  130. ---- ------ ------ 
  131. 李军 语文   74.00 
  132. 李军 数学   84.00 
  133. 李军 英语   94.00 
  134. 李军 平均分 84.00 
  135. 李军 总分   252.00 
  136. 王刚 语文   75.00 
  137. 王刚 数学   83.00 
  138. 王刚 英语   93.00 
  139. 王刚 平均分 83.33 
  140. 王刚 总分   251.00 
  141. ------------------ 
  142. */  
  143. select * from  
  144. (  
  145.  select sname as sname , subject = '语文' , scores = 语文 from tb   
  146.  union all  
  147.  select sname as sname , subject = '数学' , scores = 数学 from tb  
  148.  union all  
  149.  select sname as sname , subject = '英语' , scores = 英语 from tb  
  150.  union all  
  151.  select sname as sname , subject = '平均分' , scores = cast((语文 + 数学 + 英语)*1.0/3 as decimal(18,2)) from tb  
  152.  union all  
  153.  select sname as sname , subject = '总分' , scores = 语文 + 数学 + 英语 from tb  
  154. ) t  
  155. order by sname , case subject when '语文' then 1 when '数学' then 2 when '英语' then 3 when '平均分' then 4 when '总分' then 5 end  
  156. drop table tb  

原文链接http://blog.youkuaiyun.com/coleling/article/details/5973766

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值