sql server和oracle 行列转换

本文介绍数据库中行列转换的方法,包括使用SQL语句实现成绩表和销售数据表的转换,以及通过函数合并字段等实用技巧。

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

1. 行列转换--普通

假设有张学生成绩表(CJ)如下
Name Subject Result
张三 语文 80
张三 数学 90
张三 物理 85
李四 语文 85
李四 数学 92
李四 物理 82

想变成
姓名 语文 数学 物理
张三 80 90 85
李四 85 92 82

测试: --by yanleigis email:landgis@126.com

create table CJ
(
id int IDENTITY(1,1) not null primary key, --自增加1
Name varchar(8),
Subject varchar(8),
Result float
)

alter table cj alter column result numeric(8,1) --设置小数位数
insert into CJ (Name,Subject,Result) values ('张三','语文',80)
insert into CJ (Name,Subject,Result) values ('张三', '数学', 90)
insert into CJ (Name,Subject,Result) values ('张三','物理', 85)
insert into CJ (Name,Subject,Result) values ('李四','语文', 85)
insert into CJ (Name,Subject,Result) values ('李四','数学', 92)
insert into CJ (Name,Subject,Result) values ('李四', '物理', 82)

declare @sql varchar(4000)
set @sql = 'select Name'
select @sql = @sql + ',sum(case Subject when '''+Subject+''' then Result end) ['+Subject+']'
from (select distinct Subject from CJ) as a
select @sql = @sql+' from cj group by name'
PRINT @sql --打印变量的值,注释两种方法--,/**/
exec(@sql)
select Name,sum(case Subject when '数学' then Result end) [数学],sum(case Subject when '物理' then Result end) [物理],sum(case Subject when '语文' then Result end) [语文] from cj group by name


2. 行列转换--合并

有表A,
id pid
1 1
1 2
1 3
2 1
2 2
3 1
如何化成表B:
id pid
1 1,2,3
2 1,2
3 1

创建一个合并的函数
create function fmerg(@id int)
returns varchar(8000)
as
begin
declare @str varchar(8000)
set @str=''
select @str=@str+','+cast(pid as varchar) from 表A where id=@id set @str=right(@str,len(@str)-1)
return(@str)
End
go

--调用自定义函数得到结果
select distinct id,dbo.fmerg(id) from 表A

测试:

create table 表A
(
id int,
pid int)

insert into 表A values (1,1);
insert into 表A values (1,2);
insert into 表A values (1,3);
insert into 表A values (2,1);
insert into 表A values (2,2);
insert into 表A values (3,1);

create function fmerg(@id int)
returns varchar(8000)
as
begin
declare @str varchar(8000)
set @str=''
select @str=@str+','+cast(pid as varchar) from 表A where id=@id set @str=right(@str,len(@str)-1)
return(@str)
End
go

select distinct id,dbo.fmerg(id) from 表A

来自:http://www.cnblogs.com/stu-acer/archive/2006/05/16/401445.html

下面的是Oracle行列转换实战(转载)

行列转换实例
None.gif表ttt有三个字段
None.gifseq--序列
None.gifjcxm--检查项目
None.gifzhi--值
None.gif
None.gif数据分别如下:
None.gifseq   jcxm  zhi
None.gif-----------------------
None.gif11     1    0.50
None.gif11     2    0.21
None.gif11     3    0.25
None.gif12     1    0.24
None.gif12     2    0.30
None.gif12     3    0.22
None.gif
None.gif实现功能
None.gif创建视图时移动行值为列值
None.gif
None.gif
None.gifcreateviewv_view1
None.gifas
None.gifselectseq,
None.gifsum(decode(jcxm,1,zhi))检测项目1,
None.gifsum(decode(jcxm,2,zhi))检测项目2,
None.gifsum(decode(jcxm,3,zhi))检测项目3
None.giffromttt
None.gifgroupbyseq;
None.gif
None.gif序号检测项目1  检测项目2  检测项目3
None.gif11     0.50    0.21     0.25
None.gif12     0.24    0.30     0.22
None.gif
None.gif
None.gif
None.gif技巧:
None.gif用THEN中的0和1来进行统计(SUM)
None.gif
None.gifjcxmzhi
None.gif--------
None.gifa1
None.gifb1
None.gifa3
None.gifd2
None.gife4
None.giff5
None.gifa5
None.gifd3
None.gifd6
None.gifb5
None.gifc4
None.gifb3
None.gif求他的zhi既是1,也是3,也是5的jcxm
None.gif方法一
None.gifselectjcxm
None.giffromttt
None.gifgroupbyjcxm
None.gifhavingsum(decode(zhi,1,-1,3,-1,5,-1,0))=-3
None.gif方法二
None.gifselectjcxmfromttt
None.gifgroupbyjcxmhaving(sign(sum(decode(zhi,1,-1,0)))+
None.gifsign(sum(decode(zhi,3,-1,0)))+sign(sum(decode(zhi,5,-1,0)))<=-3);
None.gif
None.gif----------
None.gifa
None.gifb
None.gif说明:
None.gifsign()函数根据某个值是0、正数还是负数,分别返回0、1、-1
None.gif所以可以用sign和decode来完成比较字段大小来区某个字段
None.gifselectdecode(sign(字段1-字段2),-1,字段3,字段4)fromdual;
None.gif
None.gifsign是一个对于写分析SQL有很强大的功能
None.gif下面我对sign进行一些总结:
None.gif但属性student取0和1以外的值,或者student取两个以上的标法值,问题就不会这么简单了
None.gif解决办法就是特征函数(abs(),sign())
None.gif
None.gif常用的特征算法
None.gif[A=B]=1-abs(sign(A-B))
None.gif[A!=B]=abs(sign(A-B))
None.gif[A<B]=1-sign(1+sign(A-B))
None.gif不能用-sign(A-B):因为如果不满足A<b则返回-1,而不是0,这样就不能用在字段选择上了
None.gif[A<=B]=sign(1-sign(A-B))
None.gif[A>B]=1-sign(1-sign(A-B))
None.gif[A>=B]=sign(1+sign(A-B)))
None.gif[NOTα]=1-d[α]
None.gif[αANDb]=d[α]*d[b](6)
None.gif[αORb]=sign(d[α]+d[b])
None.gif
None.gif例如:
None.gifA<BDecode(Sign(A-B),-1,1,0)
None.gif
None.gifA<=BDecode(Sign(A-B),1,0,1)
None.gif
None.gifA>BDecode(Sign(A-B),1,1,0)
None.gif
None.gifA>=BDecode(Sign(A-B),-1,0,1)
None.gif
None.gifA=BDecode(A,B,1,0)
None.gifAbetweenBandCDecode(Sign(A-B),-1,0,
None.gifDecode(Sign(A-C),1,0,1))
None.gifAisnullDecode(A,null,1,0)
None.gifAisnotnullDecode(A,null,0,1)Ain
None.gif(B1,B2,dot.gif,Bn)Decode(A,B1,1,B2,1,dot.gif,Bn,1,0)
None.gifnorLogADecode(LogA,0,1,0)
None.gif(1-Sign(LogA))
None.gifLogAandLogBLogA*LogB
None.gifLogAorLogBLogA+LogB
None.gifLogAxorLogBDecode(Sign(LogA),Sign(LogB),0,1)
None.gifMod(Sign(LogA),Sign(LogB),2
None.gif
None.gif
None.gif>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
None.gif
None.gif[NextPage]
None.gif另外一个关于成绩的分析例子
None.gif
None.gifSELECT
None.gifSUM(CASEWHENcj<60THEN1ELSE0END)as"notpassed",
None.gifSUM(CASEWHENcjBETWEEN60AND79THEN1ELSE0END)as
None.gif"passed",
None.gifSUM(CASEWHENcjBETWEEN80AND89THEN1ELSE0END)as
None.gif"good",
None.gifSUM(CASEWHENcj>=90THEN1ELSE0END)as"Excellent"
None.gifFROMcjtable;
None.gif
None.gifdecode用法2
None.gif表、视图结构转化
None.gif现有一个商品销售表sale,表结构为:
None.gifmonth   char(6)     --月份
None.gifsell    number(10,2)   --月销售金额
None.gif
None.gif现有数据为:
None.gif200001  1000
None.gif200002  1100
None.gif200003  1200
None.gif200004  1300
None.gif200005  1400
None.gif200006  1500
None.gif200007  1600
None.gif200101  1100
None.gif200202  1200
None.gif200301  1300
None.gif
None.gif想要转化为以下结构的数据:
None.gifyear   char(4)     --年份
None.gif---------------------------------
None.gif-------------------
None.gifmonth1  number(10,2)   --1月销售金额
None.gifmonth2  number(10,2)   --2月销售金额
None.gifmonth3  number(10,2)   --3月销售金额
None.gifmonth4  number(10,2)   --4月销售金额
None.gifmonth5  number(10,2)   --5月销售金额
None.gifmonth6  number(10,2)   --6月销售金额
None.gifmonth7  number(10,2)   --7月销售金额
None.gifmonth8  number(10,2)   --8月销售金额
None.gifmonth9  number(10,2)   --9月销售金额
None.gifmonth10 number(10,2)  --10月销售金额
None.gifmonth11 number(10,2)  --11月销售金额
None.gifmonth12 number(10,2)  --12月销售金额
None.gif
None.gif结构转化的SQL语句为:
None.gifcreateorreplaceview
None.gifv_sale(year,month1,month2,month3,month4,month5,month6,month7,month8,month9,month10,month11,month12)
None.gifas
None.gif    select
None.gif    substrb(month,1,4),
None.gif    sum(decode(substrb(month,5,2),'01',sell,0)),
None.gif    sum(decode(substrb(month,5,2),'02',sell,0)),
None.gif    sum(decode(substrb(month,5,2),'03',sell,0)),
None.gif    sum(decode(substrb(month,5,2),'04',sell,0)),
None.gif    sum(decode(substrb(month,5,2),'05',sell,0)),
None.gif    sum(decode(substrb(month,5,2),'06',sell,0)),
None.gif    sum(decode(substrb(month,5,2),'07',sell,0)),
None.gif    sum(decode(substrb(month,5,2),'08',sell,0)),
None.gif    sum(decode(substrb(month,5,2),'09',sell,0)),
None.gif    sum(decode(substrb(month,5,2),'10',sell,0)),
None.gif    sum(decode(substrb(month,5,2),'11',sell,0)),
None.gif    sum(decode(substrb(month,5,2),'12',sell,0))
None.gif    fromsale
None.gif    groupbysubstrb(month,1,4);
None.gif
None.gif体会:要用decode/groupby/orderby/sign/sum来实现不同报表的生成
None.gif>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
None.gifCASE应用
None.gif
None.gif11部门a800男
None.gif22部门b900女
None.gif33部门a400男
None.gif44部门d1400女
None.gif55部门e1200男
None.gif66部门f500男
None.gif77部门a300女
None.gif88部门d1000男
None.gif99部门d1230女
None.gif1010部门b2000女
None.gif1111部门c2000男
None.gif1212部门b1200男
None.gif
None.gifSELECTjcxmas部门,COUNT(seq)as人数,
None.gifSUM(CASESEXWHEN1THEN1ELSE0END)as男,
None.gifSUM(CASESEXWHEN2THEN1ELSE0END)as女,
None.gifSUM(CASESIGN(zhi-800)WHEN-1THEN1ELSE0END)as
None.gif小于800元,
None.gifSUM((CASESIGN(zhi-800)*SIGN(zhi-1000)
ExpandedBlockStart.gifContractedBlock.gif/**//*用*来实现<和>功能*/
None.gifWHEN-1THEN1ELSE0END)+(CASEzhi
None.gifWHEN800THEN1ELSE0END))as从800至999,
ExpandedBlockStart.gifContractedBlock.gif/**//*注意别名不能以数字开头*/
None.gifSUM((CASESIGN(zhi-1000)*SIGN(zhi-1200)
None.gifWHEN-1THEN1ELSE0END)+(CASEzhi
None.gifWHEN1000THEN1ELSE0END))as从1000元至1199元,
None.gifSUM((CASESIGN(zhi-1200)WHEN1THEN1ELSE0END)
None.gif+(CASEzhiWHEN1200THEN1ELSE0END))as大于1200元
None.gifFroMttt
None.gifGROUPBYjcxm
None.gif
None.gif部门名人数男女小于800元从800至999从1000元至1199元大于1200元
None.gif部门a321210
None.gif0
None.gif部门b312010
None.gif2
None.gif部门c110000
None.gif1
None.gif部门d312001
None.gif2
None.gif部门e110000
None.gif1
None.gif部门f110100
None.gif0
None.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值