Oracle實(shí)現(xiàn)行列轉(zhuǎn)換的方法分析
本文實(shí)例講述了Oracle實(shí)現(xiàn)行列轉(zhuǎn)換的方法。分享給大家供大家參考,具體如下:
1、固定列數(shù)的行列轉(zhuǎn)換
如:
student subject grade --------- ---------- -------- student1 語(yǔ)文 80 student1 數(shù)學(xué) 70 student1 英語(yǔ) 60 student2 語(yǔ)文 90 student2 數(shù)學(xué) 80 student2 英語(yǔ) 100 ……
轉(zhuǎn)換為:
語(yǔ)文 數(shù)學(xué) 英語(yǔ) student1 80 70 60 student2 90 80 100 ……
語(yǔ)句如下:
select student, sum(decode(subject,'語(yǔ)文', grade,null)) "語(yǔ)文", sum(decode(subject,'數(shù)學(xué)', grade,null)) "數(shù)學(xué)", sum(decode(subject,'英語(yǔ)', grade,null)) "英語(yǔ)" from table group by student;
2、不定列行列轉(zhuǎn)換
如:
c1 c2 --- ----------- 1 我 1 是 1 誰(shuí) 2 知 2 道 3 不 ……
轉(zhuǎn)換為
1 我是誰(shuí) 2 知道 3 不
這一類型的轉(zhuǎn)換可以借助于PL/SQL來(lái)完成,這里給一個(gè)例子
CREATE OR REPLACE FUNCTION get_c2(tmp_c1 NUMBER) RETURN VARCHAR2 IS Col_c2 VARCHAR2(4000); BEGIN FOR cur IN (SELECT c2 FROM t WHERE c1=tmp_c1) LOOP Col_c2 := Col_c2||cur.c2; END LOOP; Col_c2 := rtrim(Col_c2,1); RETURN Col_c2; END; select distinct c1 ,get_c2(c1) cc2 from table;
或者不用pl/sql,利用分析函數(shù)和 CONNECT_BY 實(shí)現(xiàn):
SELECT c1, SUBSTR (MAX (SYS_CONNECT_BY_PATH (c2, ';')), 2) NAME FROM (SELECT c1, c2, rn, LEAD (rn) OVER (PARTITION BY c1 ORDER BY rn) rn1 FROM (SELECT c1, c2, ROW_NUMBER () OVER (ORDER BY c2) rn FROM t)) START WITH rn1 IS NULL CONNECT BY rn1 = PRIOR rn GROUP BY c1;
3、列數(shù)不固定(交叉表行列轉(zhuǎn)置)
這種是比較麻煩的一種,需要借助pl/sql:
原始數(shù)據(jù):
CLASS1 CALLDATE CALLCOUNT 1 2005-08-08 40 1 2005-08-07 6 2 2005-08-08 77 3 2005-08-09 33 3 2005-08-08 9 3 2005-08-07 21
轉(zhuǎn)置后:
CALLDATE CallCount1 CallCount2 CallCount3 ------------ ---------- ---------- ---------- 2005-08-09 0 0 33 2005-08-08 40 77 9 2005-08-07 6 0 21
試驗(yàn)如下:
1). 建立測(cè)試表和數(shù)據(jù)
CREATE TABLE t( class1 VARCHAR2(2 BYTE), calldate DATE, callcount INTEGER ); INSERT INTO t(class1, calldate, callcount) VALUES ('1', TO_DATE ('08/08/2005', 'MM/DD/YYYY'), 40); INSERT INTO t(class1, calldate, callcount) VALUES ('1', TO_DATE ('08/07/2005', 'MM/DD/YYYY'), 6); INSERT INTO t(class1, calldate, callcount) VALUES ('2', TO_DATE ('08/08/2005', 'MM/DD/YYYY'), 77); INSERT INTO t(class1, calldate, callcount) VALUES ('3', TO_DATE ('08/09/2005', 'MM/DD/YYYY'), 33); INSERT INTO t(class1, calldate, callcount) VALUES ('3', TO_DATE ('08/08/2005', 'MM/DD/YYYY'), 9); INSERT INTO t(class1, calldate, callcount) VALUES ('3', TO_DATE ('08/07/2005', 'MM/DD/YYYY'), 21); COMMIT ;
2). 建立ref cursor準(zhǔn)備輸出結(jié)果集
CREATE OR REPLACE PACKAGE pkg_getrecord IS TYPE myrctype IS REF CURSOR; END pkg_getrecord;
3). 建立動(dòng)態(tài)sql交叉表函數(shù),輸出結(jié)果集
CREATE OR REPLACE FUNCTION fn_rs RETURN pkg_getrecord.myrctype IS s VARCHAR2 (4000); CURSOR c1 IS SELECT ',sum(case when Class1=' || class1 || ' then CallCount else 0 end)' || ' "CallCount' || class1 || '"' c2 FROM t GROUP BY class1; r1 c1%ROWTYPE; list_cursor pkg_getrecord.myrctype; BEGIN s := 'select CallDate '; OPEN c1; LOOP FETCH c1 INTO r1; EXIT WHEN c1%NOTFOUND; s := s || r1.c2; END LOOP; CLOSE c1; s := s || ' from T group by CallDate order by CallDate desc '; OPEN list_cursor FOR s; RETURN list_cursor; END fn_rs;
4). 測(cè)試在sql plus下執(zhí)行:
var results refcursor; exec :results := fn_rs; print results; CALLDATE CallCount1 CallCount2 CallCount3 --------------- ---------- ---------- ---------- 2005-08-09 0 0 33 2005-08-08 40 77 9 2005-08-07 6 0 21
說(shuō)明:decode
DECODE(value, if1, then1, if2,then2, if3,then3, . . . else )
Value 代表某個(gè)表的任何類型的任意列或一個(gè)通過(guò)計(jì)算所得的任何結(jié)果。當(dāng)每個(gè)value值被測(cè)試,如果value的值為if1,Decode 函數(shù)的結(jié)果是then1;如果value等于if2,Decode函數(shù)結(jié)果是then2;等等。事實(shí)上,可以給出多個(gè)if/then 配對(duì)。如果value結(jié)果不等于給出的任何配對(duì)時(shí),Decode 結(jié)果就返回else 。
另外,還可以用decoder函數(shù)來(lái)比較大小,如下:
select decode(sign(變量1-變量2),-1,變量1,變量2) from dual; --取較小值
sign()函數(shù)根據(jù)某個(gè)值是0、正數(shù)還是負(fù)數(shù),分別返回0、1、-1
例如:
變量1=10,變量2=20
則sign(變量1-變量2)返回-1,decode解碼結(jié)果為“變量1”,達(dá)到了取較小值的目的。
更多關(guān)于Oracle相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Oracle常用函數(shù)匯總》、《Oracle日期與時(shí)間操作技巧總結(jié)》及《php+Oracle數(shù)據(jù)庫(kù)程序設(shè)計(jì)技巧總結(jié)》
希望本文所述對(duì)大家Oracle數(shù)據(jù)庫(kù)程序設(shè)計(jì)有所幫助。
相關(guān)文章
Oracle中的INSTR,NVL和SUBSTR函數(shù)的用法詳解
這篇文章主要介紹了Oracle中的INSTR,NVL和SUBSTR函數(shù)的用法詳解,需要的朋友可以參考下2017-02-02Oracle存儲(chǔ)過(guò)程游標(biāo)用法分析
這篇文章主要介紹了Oracle存儲(chǔ)過(guò)程游標(biāo)用法,結(jié)合實(shí)例形式分析了游標(biāo)的使用步驟與相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06分享ORACLE SEQUENCE跳號(hào)總結(jié)
在ORACLE數(shù)據(jù)庫(kù)中,序列(SEQUENCE)是使用非常頻繁的一個(gè)數(shù)據(jù)庫(kù)對(duì)象,但是有時(shí)候會(huì)遇到序列(SEQUECNE)跳號(hào)(skip sequence numbers)的情形,那么在哪些情形下會(huì)遇到跳號(hào)呢,下面通過(guò)本文給大家詳解介紹,一起看看吧2017-09-09Windows Sever 2012下Oracle 12c安裝配置方法圖文教程
這篇文章主要為大家詳細(xì)介紹了Windows Sever 2012下Oracle 12c安裝配置方法圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04在Mac OS上安裝Oracle數(shù)據(jù)庫(kù)的基本方法
這篇文章主要介紹了在Mac OS上安裝Oracle數(shù)據(jù)庫(kù)的基本方法,Oracle是甲骨文公司的一款收費(fèi)數(shù)據(jù)庫(kù)軟件,需要的朋友可以參考下2015-12-12