oracle行列互换sql,ORACLE sql行列转置的实现方法

总结一下关于行列转置的实现方法1、固定列数的行列转换

student subject grade--------- ---------- --------student1

语文80

student1 数学70

student1 英语60

student2 语文90

student2 数学80

student2 英语100

……

转换为

student 语文 数学 英语

student1807060

student29080100

……

语句如下:

create table stu(

id number,

subject varchar2(30),

grade number);

insert into stu values(1, '语文',90);

insert into stu values(1, '英语',80);

insert into stu values(1, '数学',85);

insert into stu values(1, '体育',70);

insert into stu values(2, '语文',90);

insert into stu values(2, '英语',80);

insert into stu values(2, '数学',85);

insert into stu values(2, '体育',70);

select id,

sum(

decode(subject,'语文',grade, 0))语文,

sum(decode(subject,'英语', grade,0))英语,

sum(decode(subject,'数学', grade,0))数学,

sum(decode(subject,'体育', grade,0))体育

from stu

group by id;

2、不定列行列转换

c1 c2--- -----------1我1是1谁2知2道3不

……

转换为1我是谁2知道3不

这一类型的转换可以借助于PL/SQL来完成,这里给一个例子CREATEORREPLACEFUNCTIONget_c2(tmp_c1NUMBER)RETURNVARCHAR2IS

Col_c2VARCHAR2(4000);BEGINFORcurIN(SELECTc2FROMtWHEREc1=tmp_c1)

LOOP

Col_c2 :=Col_c2||cur.c2;ENDLOOP;

Col_c2 :=rtrim(Col_c2,1);RETURNCol_c2;END;

selectdistinctc1 ,get_c2(c1) cc2fromtable;

或者不用pl/sql,利用分析函数和 CONNECT_BY 实现:

SELECTc1, SUBSTR (MAX(SYS_CONNECT_BY_PATH (c2,';')),2) NAME

FROM(SELECTc1, c2, rn, LEAD (rn)OVER(PARTITIONBYc1ORDERBYrn)

rn1

FROM(SELECTc1, c2, ROW_NUMBER ()OVER(ORDERBYc2) rn

FROMt))

STARTWITHrn1ISNULL

CONNECTBYrn1=PRIOR rnGROUPBYc1;

3、列数不固定(交叉表行列转置)

这种是比较麻烦的一种,需要借助pl/sql:

原始数据:

CLASS1 CALLDATE

CALLCOUNT12005-08-084012005-08-07622005-08-087732005-08-093332005-08-08932005-08-0721

转置后:

CALLDATE CallCount1 CallCount2 CallCount3------------ ----------

----------

----------2005-08-0900332005-08-08407792005-08-07 6     021

试验如下:1). 建立测试表和数据CREATETABLEt(

class1VARCHAR2(2BYTE),

calldate DATE,

callcountINTEGER

);

INSERTINTOt(class1, calldate, callcount)VALUES('1', TO_DATE

('08/08/2005','MM/DD/YYYY'),40);

INSERTINTOt(class1, calldate, callcount)VALUES('1', TO_DATE

('08/07/2005','MM/DD/YYYY'),6);

INSERTINTOt(class1, calldate, callcount)VALUES('2', TO_DATE

('08/08/2005','MM/DD/YYYY'),77);

INSERTINTOt(class1, calldate, callcount)VALUES('3', TO_DATE

('08/09/2005','MM/DD/YYYY'),33);

INSERTINTOt(class1, calldate, callcount)VALUES('3', TO_DATE

('08/08/2005','MM/DD/YYYY'),9);

INSERTINTOt(class1, calldate, callcount)VALUES('3', TO_DATE

('08/07/2005','MM/DD/YYYY'),21);

COMMIT;

2). 建立ref cursor准备输出结果集CREATEORREPLACEPACKAGE pkg_getrecordIS

TYPE myrctypeISREFCURSOR;ENDpkg_getrecord;/

3). 建立动态sql交叉表函数,输出结果集CREATEORREPLACEFUNCTIONfn_rs

RETURNpkg_getrecord.myrctypeIS

sVARCHAR2(4000);

CURSORc1IS

SELECT',sum(case when Class1='

||class1

||'then CallCount else 0 end)'

||'"CallCount'

||class1

||'"'c2

FROMt

GROUPBYclass1;

r1 c1%ROWTYPE;

list_cursor pkg_getrecord.myrctype;BEGIN

s :='select CallDate';

OPENc1;

LOOP

FETCHc1INTOr1;

EXITWHENc1%NOTFOUND;

s :=s||r1.c2;

ENDLOOP;

CLOSEc1;

s :=s||'from T group by CallDate order by CallDate desc';

OPENlist_cursorFORs;

RETURNlist_cursor;ENDfn_rs;/

4). 测试在sql plus下执行:varresults refcursor;exec:results

:=fn_rs;printresults;

CALLDATE CallCount1 CallCount2 CallCount3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值