sql行列轉置的實現方法

aricyoung發表於2008-03-03
總結一下關於行列轉置的實現方法1、固定列數的行列轉換

student subject grade
--------- ---------- --------
student1 語文 80
student1 數學
70
student1 英語
60
student2 語文
90
student2 數學
80
student2 英語
100
……
轉換為
student 語文 數學 英語
student1
80 70 60
student2
90 80 100
……
語句如下:
select student, sum(decode(subject,'語文', grade,null)) "語文",sum(decode(subject,'數學', grade,null)) "數學",sum(decode(subject,'英語', grade,null)) "英語"from tablegroup by student;[@more@]2、不定列行列轉換

c1 c2
--- -----------
111223
……
轉換為
1
我是誰2 知道3

這一型別的轉換可以藉助於PL
/
SQL來完成,這裡給一個例子CREATE OR REPLACE FUNCTION get_c2(tmp_c1 NUMBER)RETURN VARCHAR2IS
Col_c2
VARCHAR2(4000);BEGINFOR 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,利用分析函式和 CONNECT_BY 實現:
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 rnGROUP BY c1;

3
、列數不固定(交叉錶行列轉置)
這種是比較麻煩的一種,需要藉助pl
/
sql:

原始資料:
CLASS1 CALLDATE CALLCOUNT
1 2005-08-08 40
1 2005-08-07 62 2005-08-08 773 2005-08-09 333 2005-08-08 93 2005-08-07 21

轉置後:
CALLDATE CallCount1 CallCount2 CallCount3
------------ ---------- ---------- ----------2005-08-09 0 0 332005-08-08 40 77 92005-08-07  6      0 21

試驗如下:
1). 建立測試表和資料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準備輸出結果集 CREATE OR REPLACE PACKAGE pkg_getrecordIS
TYPE myrctype
IS REF CURSOR;END pkg_getrecord;/
3). 建立動態sql交叉表函式,輸出結果集 CREATE OR REPLACE FUNCTION fn_rs
RETURN
pkg_getrecord.myrctypeIS
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
). 測試在sql plus下執行:var results refcursor;exec :results := fn_rs;print results;
CALLDATE CallCount1 CallCount2 CallCount3
--------------- ---------- ---------- ----------
2005-08-09 0 0 332005-08-08 40 77 92005-08-07 6 0 21

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/787895/viewspace-1000345/,如需轉載,請註明出處,否則將追究法律責任。

相關文章