SQLserver动态⾏转列
在学习数据库的时候,遇到了怎么把数据表中的内容转变成数据表的字段,在此,记录⼀下⾃⼰对⾏转列的理解
⽐如有个学⽣成绩表:
stuid:学号
course:科⽬
score:成绩
表的内容为:
stuid course score
0101 语⽂ 78
0101 数学 90
0101 英语 67
0101 物理 88
⽽我们想要的是类似下表:
stuid 语⽂ 数学 英语 物理
0101 78 90 67 88
这个时候就需要⽤到⾏转列,⾏转列有动态与静态之分:
静态⾏转列:通过sql语句,静态的进⾏转换,⼀旦原表的数据有改动,⽐如增加化学成绩,或者删除物理成绩,我们就得重新改变sql语句:
就上表,转换的sql语句为:
select stuid,
max(case course when'语⽂'then score else0end)语⽂,
max(case course when'数学'then score else0end)数学,
max(case course when'英语'then score else0end)英语,
max(case course when'物理'then score else0end)物理
from scores --表名
group by stuid --分组查询
主要知识:max(),case,group by 分组查询。
max()取最⼤值。
case:我的理解是从⼏个选项中选择,⽐如:
case course when '语⽂' then score else 0 end
当course 为语⽂时,case返回对应的score与0当中的⼀个,在本例中,查询第⼀条数据:
0101 语⽂ 78
此时:course=‘语⽂’,score=78,则case返回78,
当查询第⼆条数据的时候:
0101 数学 90
course=‘语⽂’不存在,则返回 0 (else 0 )增加字段的sql语句
以此类推得:
max(78,0,0,0),
max()取最⼤值,最后的数据就是 78,
所谓静态,就是我们⼿动静态的获取每⼀个字段(语⽂,数学,英语,物理),⼀旦科⽬有所改变,我们就得修改sql语句,不怎么⽅便
⽽动态⾏转列就可以避免这种情况,它是动态的⾃⼰根据原表中的数据,获取字段名:
declare@sql varchar(8000) --申明⼀个变量 @sql,数据类型为 varchar(8000)
set@sql='select stuid,' -- 使⽤ set 为@sql 赋值
select@sql=@sql+'max(case course when '''+course +'''then score else 0 end)'+''''+course +''','
from (select distinct course from scores) as sc --使⽤select 为@sql赋值
set@sql=left(@sql,len(@sql)-1)+'from scores group by stuid'
exec(@sql) --执⾏@sql
注意:在sql语句中,使⽤单引号 ’ 来确定字符串的范围,如果字符串本⾝含有单引号如:‘ 姓名:‘张三’,性别:‘男’ ’,这时候需要⽤ '' ,即两个单引号来表⽰字符串本⾝的单引
号。
set 语句⼤家应该很熟悉,为变量赋值,⽽select 其实也可以看做⼀个赋值关键字,不过是⼀个循环赋值(个⼈理解)⽽已。
如:select stuid from students,表⽰将students表中的所有stuid属性值(1,2,)赋值给变量stuid:
stuid=1,对stuid操作(如输出stuid=1)
stuid=2,对stuid操作(如输出stuid=2)
stuid=3,对stuid操作(如输出stuid=3)
所以,上边的动态⾏转列中的select赋值语句可以理解为:
将from 后边的(select course from scores)所查询到的结果,逐⼀赋值给course变量,并且,每⼀次复制后的操作为:字符串连接
所以
select @sql =@sql +'max(case course when '''+course +'''then score else 0 end)'+''''course +''','
from (select distinct course from scores)的执⾏过程为:
@sql='select stuid,'+'max(case course when '''+语⽂+'''then score else 0 end)'+''''语⽂+''',' --@1
@sql=@1+'max(case course when '''+数学+'''then score else 0 end)'+''''数学+''',' --@2
@sql=@2+'max(case course when '''+英语+'''then score else 0 end)'+''''英语+''',' --@3
@sql=@3+'max(case course when '''+物理+'''then score else 0 end)'+''''物理+''',' --@4
是不是和静态的代码很像?因为它们的原理都是⼀样的:max(),case,group by,不同的是动态⾏转列使⽤动态拼接字符串的⽅法,动态的从原表当中出我们需要的字段,如果原表当中删除了物理成绩,我们就查不到物理成绩,⾃然也就不会将科⽬
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论