sql中行列互换问题

感觉还是蛮全的

/* 

标题 :普通行列 转换 (version 2.0)  
问题 :假 学生成 (tb) 如下 :  
姓名  程 分数  
三   74  
三 数学  83  
三 物理  93  
李四   74  
李四 数学  84  
李四 物理  94  
( 得到如下 ) : 
姓名  文 数学 物理 
---- ---- ---- ----  
李四  74   84   94  
三 74   83   93  
-------------------  
*/  
  
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  
  
--SQL SERVER 2000  SQL, 程只有 文、数学、物理 门课 程。(以下同)  
select 姓名  as 姓名 ,  
  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 姓名  
  
--SQL SERVER 2000  动态 SQL, 程不止 文、数学、物理 门课 程。(以下同)  
declare @sql varchar ( 8000 )  
set @sql = 'select  姓名 '  
select @sql = @sql + ' , max(case  程 when ''' + 程  + ''' then  分数 else 0 end) [' + 程  + ']'  
from  ( select distinct 程  from  tb)  as  a  
set @sql = @sql + ' from tb group by  姓名'  
exec ( @sql
  
--SQL SERVER 2005  SQL  
select * from  ( select * from  tb) a pivot ( max ( 分数)  for 程  in  ( 文,数学,物理)) b  
  
--SQL SERVER 2005  动态 SQL  
declare @sql varchar ( 8000 )  
select @sql = isnull ( @sql + ','  ,  '' + 程  from  tb  group by  
exec  ( 'select * from (select * from tb) a pivot (max( 分数) for  程 in (' + @sql + ')) b' )  
  
---------------------------------  
  
/*  
问题 :在上述 果的基 上加平均分, 分,得到如下 果:  
姓名  文 数学 物理 平均分  分 
---- ---- ---- ---- ------ ----  
李四 74   84   94   84.00 252  
三 74   83   93   83.33 250  
*/  
  
--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 物理,  
  cast ( avg ( 分数 * 1.0 as decimal ( 18 , 2 ))  平均分,  
  sum ( 分数)   
from  tb  
group by 姓名  
  
--SQL SERVER 2000  动态 SQL  
declare @sql varchar ( 8000 )  
set @sql = 'select  姓名 '  
select @sql = @sql + ' , max(case  程 when ''' + 程  + ''' then  分数 else 0 end) [' + 程  + ']'  
from  ( select distinct 程  from  tb)  as  a  
set @sql = @sql + ' , cast(avg( 分数*1.0) as decimal(18,2)) 平均分 , sum(分数)  分 from tb group by 姓名'  
exec ( @sql
  
--SQL SERVER 2005  SQL  
select  m. *  , n. 平均分 , n. 分  from  
( select * from  ( select * from  tb) a pivot ( max ( 分数)  for 程  in  ( 文,数学,物理)) b) m,  
( select 姓名 ,  cast ( avg ( 分数 * 1.0 as decimal ( 18 , 2 ))  平均分 ,  sum ( 分数)  分  from  tb  group by 姓名) n  
where  m. 姓名  =  n. 姓名  
  
--SQL SERVER 2005  动态 SQL  
declare @sql varchar ( 8000 )  
select @sql = isnull ( @sql + ','  ,  '' + 程  from  tb  group by  
exec  ( 'select m.* , n. 平均分 , n. 分 from  
(select * from (select * from tb) a pivot (max( 分数) for  程 in (' + @sql + ')) b) m , 
(select  姓名 , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数)  分 from tb group by 姓名) n
where m. 姓名 = n.姓名' )  
  
drop table  tb    
  
------------------  
------------------  
  
/*  
问题 :如果上述两表互相 一下:即表 构和数据  
姓名  文 数学 物理  
 74    83    93  
李四  74    84    94  
( 得到如下 ) : 
姓名  程 分数 
---- ---- ----  
李四   74  
李四 数学  84  
李四 物理  94  
三   74  
三 数学 83  
三 物理 93  
--------------  
*/  
  
create table  tb( 姓名  varchar ( 10 ) ,  文  int  ,  数学  int  ,  物理  int )  
insert into  tb  values ( ' 三' , 74 , 83 , 93 )  
insert into  tb  values ( ' 李四' , 74 , 84 , 94 )  
go  
  
--SQL SERVER 2000  SQL  
select * from  
(  
  select 姓名 ,  程  = ' 文'  ,  分数  = 文  from  tb 
  union all  
  select 姓名 ,  程  = ' 数学'  ,  分数  = 数学  from  tb  
  union all  
  select 姓名 ,  程  = ' 物理'  ,  分数  = 物理  from  tb  
) t  
order by 姓名 ,  case 程  when ' 文' then 1 when ' 数学' then 2 when ' 物理' then 3 end  
  
--SQL SERVER 2000  动态 SQL  
-- 用系 动态  
declare @sql varchar ( 8000 )  
select @sql = isnull ( @sql + ' union all '  ,  ''  )  + ' select  姓名 , [ 程] = ' + quotename (Name ,  '''' + ' , [ 分数] = ' + quotename (Name)  + ' from tb'  
from  syscolumns 
where  name!  =  N ' 姓名' and  ID  = object_id ( 'tb' -- 表名tb,不包含列名 姓名的其它列  
order by  colid  asc  
exec ( @sql + ' order by  姓名 ' )  
  
--SQL SERVER 2005  动态 SQL  
select 姓名 ,  程 , 分数  from  tb unpivot ( 分数  for 程  in ( [ 文]  ,  [ 数学]  ,  [ 物理] )) t  
  
--SQL SERVER 2005  动态 SQL ,同SQL SERVER 2000  动态 SQL  
  
--------------------  
/*  
问题 :在上述的 果上加个平均分, 分,得到如下 果:  
姓名     分数  
---- ------ ------  
李四     74.00  
李四 数学    84.00  
李四 物理    94.00  
李四 平均分  84.00  
李四     252.00  
三     74.00  
三 数学    83.00  
三 物理    93.00  
三 平均分  83.33  
三     250.00  
------------------  
*/  
  
select * from  
(  
  select 姓名  as 姓名 ,  程  = ' 文'  ,  分数  = 文  from  tb 
  union all  
  select 姓名  as 姓名 ,  程  = ' 数学'  ,  分数  = 数学  from  tb  
  union all  
  select 姓名  as 姓名 ,  程  = ' 物理'  ,  分数  = 物理  from  tb  
  union all  
  select 姓名  as 姓名 ,  程  = ' 平均分'  ,  分数  = cast (( 文  + 数学  + 物理) * 1.0 / 3 as decimal ( 18 , 2 ))  from  tb  
  union all  
  select 姓名  as 姓名 ,  程  = ' 分'  ,  分数  = 文  + 数学  + 物理  from  tb  
) t  
order by 姓名 ,  case 程  when ' 文' then 1 when ' 数学' then 2 when ' 物理' then 3 when ' 平均分' then 4 when ' 分' then 5 end  

drop table  tb  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值