sqlserver 行转列

---1、最简单的行转列 
 /*     
  
 问题:假设有张学生成绩表(tb)如下: 
 姓名 课程 分数 
 张三 语文 74 
 张三 数学 83 
 张三 物理 93 
 李四 语文 74 
 李四 数学 84 
 李四 物理 94 
  
  
 想变成(得到如下结果):  
 姓名 语文 数学 物理  
 李四 74   84   94 
 张三 74   83   93 
 */ 
 --测试用 
 IF OBJECT_ID('[tb]') IS NOT NULL DROP TABLE [tb] 
 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 
  
 --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,得到如下脚本 
 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 2005 动态SQL。 
 declare @sql varchar(8000) 
 select @sql = isnull(@sql + '],[' , '') + 课程 from tb group by 课程 
 set @sql = '[' + @sql + ']' 
 exec ('select * from (select * from tb) a pivot (max(分数) for 课程 in (' + @sql + ')) b') 
 --得到SQL SERVER 2005 静态SQL。 
 select * from (select * from tb) a pivot (max(分数) for 课程 in (语文,数学,物理)) b 
  
 --查询结果 
 /* 
 姓名         数学          物理          语文           
 ---------- ----------- ----------- -----------  
 李四         84          94          74 
 张三         83          93          74 
  
 (所影响的行数为 2 行) 
 */ 
  
  
 --2 加合计 
 /* 
 问题:在上述结果的基础上加平均分,总分,得到如下结果: 
 姓名 语文 数学 物理 平均分 总分  
 ---- ---- ---- ---- ------ ---- 
 李四 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.姓名') 
  
 其他实例 
  
 http://topic.csdn.net/u/20100708/18/55df5a90-27a7-4452-a69a-27f735539a1f.html?seed=24842417&r=66831902#r_66831902 
  
  
 --3、不同数据按照序号转为列,方法基本同 1 
  
 if object_id('tb1') is not null drop table tb1 
 go 
 CREATE table tb1 --数据表 
 ( 
 cpici varchar(10) not null, 
 cname varchar(10) not null, 
 cvalue int null  
 ) 
 --插入测试数据 
 INSERT INTO tb1 values('T501','x1',31) 
 INSERT INTO tb1 values('T501','x1',33) 
 INSERT INTO tb1 values('T501','x1',5) 
  
 INSERT INTO tb1 values('T502','x1',3) 
 INSERT INTO tb1 values('T502','x1',22) 
 INSERT INTO tb1 values('T502','x1',3) 
  
 INSERT INTO tb1 values('T503','x1',53) 
 INSERT INTO tb1 values('T503','x1',44) 
 INSERT INTO tb1 values('T503','x1',50) 
 INSERT INTO tb1 values('T503','x1',23) 
  
  
 --在sqlserver2000里需要用自增辅助 
 alter table tb1 add id int identity 
 go 
 declare @s varchar(8000) 
 set @s='select cpici ' 
 select @s=@s+',max(case when rn='+ltrim(rn)+' then cvalue end) as cvlue'+ltrim(rn) 
 from (select distinct rn from (select rn=(select count(1) from tb1 where cpici=t.cpici and id <=t.id) from tb1 t)a)t 
 set @s=@s+' from (select rn=(select count(1) from tb1 where cpici=t.cpici and id <=t.id),* from tb1 t 
 ) t group by cpici' 
  
 exec(@s) 
 go 
 alter table tb1 drop column id  
  
 --再2005就可以用row_number 
 declare @s varchar(8000) 
 set @s='select cpici ' 
 select @s=@s+',max(case when rn='+ltrim(rn)+' then cvalue end) as cvlue'+ltrim(rn) 
 from (select distinct rn from (select rn=row_number()over(partition by cpici order by getdate()) from tb1)a)t 
 set @s=@s+' from (select rn=row_number()over(partition by cpici order by getdate()),* from tb1 
 ) t group by cpici' 
  
 exec(@s) 
  
 ---结果 
 /* 
 cpici      cvlue1      cvlue2      cvlue3      cvlue4 
 ---------- ----------- ----------- ----------- ----------- 
 T501       31          33          5           NULL 
 T502       3           22          3           NULL 
 T503       53          44          50          23 
 警告: 聚合或其他 SET 操作消除了空值。 
  
 (3 行受影响) 
  
 */ 
  
  
 --测试用 
 IF OBJECT_ID('[tb]') IS NOT NULL DROP TABLE [tb] 
 GO 
 create table tb(电话号码 varchar(15), 通话时长 int ,行业 varchar(10)) 
 insert tb 
 select '13883633601', 10 ,'餐饮' union all 
 select '18689704236', 20 ,'物流' union all 
 select '13883633601', 20 ,'物流' union all 
 select '13883633601', 20 ,'汽车' union all 
 select '18689704236', 20 ,'医疗' union all 
 select '18689704236', 20 ,'it' union all 
 select '18689704236', 20 ,'汽车' union all 
 select '13883633601', 50 ,'餐饮' 
 go 
  
 declare @sql varchar(8000) 
 set @sql='select 电话号码,sum(通话时长) 通话总和' 
 select @sql=@sql+',max(case when rowid='+ltrim(rowid)+' then 行业 else '''' end) as [行业'+ltrim(rowid)+']' 
 from (select distinct rowid from (select (select count(distinct 行业) from tb where 电话号码=t.电话号码 and 行业 <=t.行业) rowid 
 from tb t) a) b 
 set @sql=@sql+' from ( select * , (select count(distinct 行业) from tb where 电话号码=t.电话号码 and 行业 <=t.行业) rowid 
 from tb t ) t group by 电话号码' 
 exec(@sql) 
  
 --结果 
 /* 
  
 (所影响的行数为 8 行) 
  
 电话号码            通话总和        行业1        行业2        行业3        行业4         
 --------------- ----------- ---------- ---------- ---------- ----------  
 13883633601     100         餐饮         汽车         物流          
 18689704236     80          it         汽车         物流         医疗 
  
 (所影响的行数为 2 行) 
  
 */ 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQL Server中,行转列是一种将表中的行数据转换为列数据的操作。根据提供的引用内容,我们可以使用PIVOT函数来实现行转列操作。首先,创建一个临时表#USER,并插入一些数据。然后使用PIVOT函数将科目列转换为新的列名,并将分数作为对应列的值。最后,使用GROUP BY语句按照姓名进行分组,并使用MAX函数获取每个科目的最大值。下面是一个示例的行转列SQL查询语句: CREATE TABLE #USER ( name NVARCHAR(100), 科目 NVARCHAR(100), 分数 DECIMAL(18,2) ) INSERT INTO #USER (name, 科目, 分数) VALUES ('张三', '语文', 100), ('张三', '英语', 80), ('张三', '数学', 60), ('张三', '物理', 70) SELECT newtemp.name, MAX(newtemp.语文) 语文, MAX(newtemp.英语) 英语, MAX(newtemp.数学) 数学, MAX(newtemp.物理) 物理 FROM #USER s PIVOT ( MAX(分数) FOR 科目 IN (语文, 英语, 数学, 物理) ) AS newtemp GROUP BY newtemp.name 这样的处理方法有助于简化前后端的处理,直接查询转换后的固定列和实体即可,无需再编写大量的特殊处理方法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [SQL Server 行转列](https://blog.csdn.net/qq_45619623/article/details/126529707)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值