(mssql)动态实现由纵变横实例整理

本文介绍了如何在SQL中通过静态方法和动态构造的方式,将数据从纵向转换为横向,详细探讨了这两种方法的实现过程,包括数据插入、对象操作和处理NULL值的技巧。

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


很多情况下,需要对数据表中的数据由纵向变横向显示

也就是由较少的列根据一定的条件转化成较多的列显示。

下面的学生成绩表就是其中的一个例子:
/*
if object_id(’tempdb..#s’) is not null
drop table #s
create table #s(stu char(8),subject char(8),score int)

insert #s(stu,score,subject)
select ’小李’ , 88 , ’数学’
union all select ’小李’ , 77 , ’英语’
union all select ’小李’ , 55 , ’政治’
union all select ’小李’ , 30 , ’语文’
union all select ’小赵’ , 66 , ’数学’
union all select ’小赵’ , 23 , ’英语’
union all select ’小赵’ , 77 , ’政治’
union all select ’小赵’ , 87 , ’语文’
union all select ’小a’ , 22 , ’数学’
union all select ’小a’ , 74 , ’英语’
union all select ’小a’ , 99 , ’政治’
union all select ’小a’ , 23 , ’语文’
union all select ’小b’ , 77 , ’数学’
union all select ’小b’ , 78 , ’英语’
union all select ’小b’ , 83 , ’政治’
union all select ’小b’ , 89 , ’语文’
union all select ’小c’ , 82 , ’数学’
union all select ’小c’ , 89 , ’英语’
union all select ’小c’ , 78 , ’政治’
union all select ’小c’ , 90 , ’语文’
union all select ’小d’ , 89 , ’数学’
union all select ’小d’ , 89 , ’英语’
union all select ’小d’ , 56 , ’政治’
union all select ’小d’ , 23 , ’语文’
union all select ’小1’ , 99 , ’数学’
union all select ’小1’ , 23 , ’英语’
union all select ’小1’ , 87 , ’政治’
union all select ’小1’ , 53 , ’语文’
union all select ’小g’ , 88 , ’数学’
union all select ’小g’ , 23 , ’英语’
union all select ’小g’ , 87 , ’政治’
union all select ’小g’ , 22 , ’语文’
union all select ’小2’ , 88 , ’数学’
union all select ’小2’ , 78 , ’英语’
union all select ’小2’ , 67 , ’政治’
union all select ’小2’ , 30 , ’语文’
union all select ’小3’ , 77 , ’数学’
union all select ’小3’ , 68 , ’英语’
union all select ’小3’ , 37 , ’政治’
union all select ’小3’ , 87 , ’语文’
union all select ’小4’ , 54 , ’数学’
union all select ’小4’ , 67 , ’英语’
union all select ’小4’ , 23 , ’政治’
union all select ’小4’ , 77 , ’语文’
union all select ’小5’ , 87 , ’数学’
union all select ’小5’ , 45 , ’英语’
union all select ’小5’ , 43 , ’政治’
union all select ’小5’ , 67 , ’语文’
union all select ’小6’ , 34 , ’数学’
union all select ’小6’ , 87 , ’英语’
union all select ’小6’ , 34 , ’政治’
union all select ’小6’ , 45 , ’语文’
union all select ’小7’ , 78 , ’数学’
union all select ’小7’ , 89 , ’英语’
union all select ’小7’ , 34 , ’政治’
union all select ’小7’ , 89 , ’语文’
union all select ’小8’ , 45 , ’数学’
union all select ’小8’ , 89 , ’英语’
union all select ’小8’ , 56 , ’政治’
union all select ’小8’ , 89 , ’语文’
union all select ’小9’ , 23 , ’数学’
union all select ’小9’ , 67 , ’英语’
union all select ’小9’ , 34 , ’政治’
union all select ’小9’ , 78 , ’语文’
*/

select * from #s

这样的结构非常合理。可往往在查看数据时需要这样的排列方式:

学生姓名   数学  英文   政治  语文 ... 总成绩
.
.
.

看到了吧?这就是一个由3列数据显示要转化成更多列的显示。

[静态方法]



要实现上述的排列方式,对MSSQL而言非常简单,采用聚合函数即可完成:

select stu,
    sum(case subject when ’数学’ then score else 0 end) 数学成绩,
    sum(case subject when ’英语’ then score else 0 end) 英文成绩,
    sum(case subject when ’政治’ then score else 0 end) 政治成绩,
    sum(case subject when ’语文’ then score else 0 end) 语文成绩,
    

    sum(stuscore) 总成绩
from #t group by stu

--实现总成绩由高到低排列
order by sum(score) desc


这样,就较简单的实现了"由纵变横"的转化

然而,在MIS中的查询中会遇到各种查询,在开发中无法预知将要查询哪几科的成绩

所以上面的句子的适用范围很小,还需要对它进行扩展。

[动态构造]



观察红色部分,可以发现除了"科目"名称之外,剩下的都是共有的部分,所以可以想到只要能构造出一个

能产生红色部分的语句,再添加上头尾部分,就完成了动态构造的功能!

--定义动态SQL变量
declare @sql nvarchar(1000)

--先添加头部!
set @sql=’select stu 学生姓名’

--动态构造,仿造红色部分

select @sql = @sql+’,sum(case subject when ’’’+subject+’’’ then score else 0 end) ’+subject+’’
--只要能完成distinct子查询,就能查询出任意课程的成绩!!
from (select distinct subject from #s where subject in(’数学’,’语文’)) a

--最后添加尾部
set @sql= @sql+’,sum(score) 总分 from #s group by stu order by sum(score) desc’

--最后执行
exec(@sql)

[说明]
动态部分的distinct部分很关键。IN部分往往要做成参数,如果要封装成存储过程的话,这部分就得借用
临时表来实现,因为IN后面不允许是变量。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值