Oracle中行列互換有哪些方法?程序員
行列轉換包括如下六種狀況:(1)列轉行。(2)行轉列。(3)多列轉換成字符串。(4)多行轉換成字符串。(5)字符串轉換成多列。(6)字符串轉換成多行。其中,重點是行轉列和字符串轉換成多行。面試
下面將分別對這幾種狀況舉例來講明。數據庫
1、列轉行微信
列轉行就是將原表中的列名做爲轉換後的表的內容。列轉行主要採用UNION ALL來完成。示例代碼以下所示:網絡
CREATE TABLE TEST_LHRapp
(ide
NAME VARCHAR2(255),函數
JANUARY NUMBER(18),學習
FEBRUARY NUMBER(18),測試
MARCH NUMBER(18),
APRIL NUMBER(18),
MAY NUMBER(18)
);
INSERT INTO TEST_LHR (NAME, JANUARY, FEBRUARY, MARCH, APRIL, MAY)
VALUES ('長壽', 58, 12, 26, 18, 269);
INSERT INTO TEST_LHR (NAME, JANUARY, FEBRUARY, MARCH, APRIL, MAY)
VALUES ('璧山', 33, 18, 17, 16, 206);
INSERT INTO TEST_LHR (NAME, JANUARY, FEBRUARY, MARCH, APRIL, MAY)
VALUES ('楊家坪', 72, 73, 79, 386, 327);
INSERT INTO TEST_LHR (NAME, JANUARY, FEBRUARY, MARCH, APRIL, MAY)
VALUES ('巫溪', 34, 9, 7, 21, 33);
INSERT INTO TEST_LHR (NAME, JANUARY, FEBRUARY, MARCH, APRIL, MAY)
VALUES ('豐都', 62, 46, 39, 36, 91);
INSERT INTO TEST_LHR (NAME, JANUARY, FEBRUARY, MARCH, APRIL, MAY)
VALUES ('武隆', 136, 86, 44, 52, 142);
COMMIT;
SELECT * FROM TEST_LHR;
下面進行列轉換:
SELECT *
FROM (SELECT T.NAME, 'JANUARY' MONTH, T.JANUARY V_NUM
FROM TEST_LHR T
UNION ALL
SELECT T.NAME, 'FEBRUARY' MONTH, T.FEBRUARY V_NUM
FROM TEST_LHR T
UNION ALL
SELECT T.NAME, 'MARCH' MONTH, T.MARCH V_NUM
FROM TEST_LHR T
UNION ALL
SELECT T.NAME, 'APRIL' MONTH, T.APRIL V_NUM
FROM TEST_LHR T
UNION ALL
SELECT T.NAME, 'MAY' MONTH, T.MAY V_NUM
FROM TEST_LHR T)
ORDER BY NAME;
2、行轉列
行轉列就是將行數據內容做爲列名。示例代碼以下所示:
CREATE TABLE T_ROW_COL_LHR(
NUM VARCHAR2(15 CHAR),
NAME VARCHAR2(20 CHAR),
SEX VARCHAR2(2 CHAR),
CLASSES VARCHAR2(30 CHAR),
COURSE_NAME VARCHAR2(50 CHAR)
);
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206211','王藝','男','06-1班','保險學');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206212','肖薇','女','06-2','保險學');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206212','肖薇','女','06-2','財務管理');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206212','肖薇','女','06-2','財務會計');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206213','陳雅詩','女','06-2','電子商務');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206213','陳雅詩','女','06-2','公共經濟學');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206213','陳雅詩','女','06-2','公司理財');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206213','陳雅詩','女','06-2','管理學原理');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206213','陳雅詩','女','06-2','保險學');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206214','李丹陽','男','06-1','保險學');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206214','李丹陽','男','06-1','財務管理');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206214','李丹陽','男','06-1','財務會計');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206214','李丹陽','男','06-1','電子商務');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206214','李丹陽','男','06-1','公共經濟學');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206215','楊伊琳','女','06-3班','環境管理學');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206215','楊伊琳','女','06-3班','管理學原理');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206215','楊伊琳','女','06-3班','商務談判');
INSERT INTO T_ROW_COL_LHR(NUM,NAME,SEX,CLASSES,COURSE_NAME) VALUES ('206216','李佳琪','男','06-2','土地估計');
SELECT * FROM T_ROW_COL_LHR;
將COURSE_NAME進行行轉列:
SELECT NUM,NAME,SEX,CLASSES,
MAX(DECODE(RN,1,COURSE_NAME,NULL)) COURSE_NAME_1,
MAX(DECODE(RN,2,COURSE_NAME,NULL)) COURSE_NAME_2,
MAX(DECODE(RN,3,COURSE_NAME,NULL)) COURSE_NAME_3,
MAX(DECODE(RN,4,COURSE_NAME,NULL)) COURSE_NAME_4,
MAX(DECODE(RN,5,COURSE_NAME,NULL)) COURSE_NAME_5
FROM (SELECT NUM,NAME,SEX,CLASSES,COURSE_NAME,
ROW_NUMBER() OVER(PARTITION BY NUM,NAME,SEX,CLASSES ORDER BY COURSE_NAME) RN
FROM T_ROW_COL_LHR)
GROUP BY NUM,NAME,SEX,CLASSES;
結果以下所示:
將COURSE_NAME列合併,示例代碼以下所示:
SELECT NUM,
NAME,
SEX,
CLASSES,
(MAX(DECODE(RN, 1, COURSE_NAME, NULL)) ||
MAX(DECODE(RN, 2, ',' || COURSE_NAME, NULL)) ||
MAX(DECODE(RN, 3, ',' || COURSE_NAME, NULL)) ||
MAX(DECODE(RN, 4, ',' || COURSE_NAME, NULL)) ||
MAX(DECODE(RN, 5, ',' || COURSE_NAME, NULL))) NAME
FROM (SELECT NUM,
NAME,
SEX,
CLASSES,
COURSE_NAME,
ROW_NUMBER() OVER(PARTITION BY NUM, NAME, SEX, CLASSES ORDER BY COURSE_NAME) RN
FROM T_ROW_COL_LHR)
GROUP BY NUM,
NAME,
SEX,
CLASSES;
結果以下所示:
3、多列轉換成字符串
使用||或CONCAT函數實現。示例代碼以下所示。
SELECT CONCAT('A','B') FROM DUAL;
4、多行轉換成字符串
示例代碼以下所示:
CREATE TABLE T_ROW_STR(
ID INT,
COL VARCHAR2(10)
);
INSERT INTO T_ROW_STR VALUES(1,'A');
INSERT INTO T_ROW_STR VALUES(1,'B');
INSERT INTO T_ROW_STR VALUES(1,'C');
INSERT INTO T_ROW_STR VALUES(2,'A');
INSERT INTO T_ROW_STR VALUES(2,'D');
INSERT INTO T_ROW_STR VALUES(2,'E');
INSERT INTO T_ROW_STR VALUES(3,'C');
COMMIT;
SELECT * FROM T_ROW_STR;
SELECT ID,
MAX(DECODE(RN, 1, COL, NULL)) ||
MAX(DECODE(RN, 2, ',' || COL, NULL)) ||
MAX(DECODE(RN, 3, ',' || COL, NULL)) STR
FROM (SELECT ID,
COL,
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY COL) AS RN
FROM T_ROW_STR) T
GROUP BY ID
ORDER BY 1;
也能夠使用SYS_CONNECT_BY_PATH來實現:
SELECT T.ID ID,
MAX(SUBSTR(SYS_CONNECT_BY_PATH(T.COL, ','), 2)) STR
FROM (SELECT ID,
COL,
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY COL) RN
FROM T_ROW_STR) T
START WITH RN = 1
CONNECT BY RN = PRIOR RN + 1
AND ID = PRIOR ID
GROUP BY T.ID;
5、字符串轉換成多列
實際上就是一個字符串拆分的問題。示例代碼以下所示:
CREATE TABLE T_COL_ROW(
ID INT,
C1 VARCHAR2(10),
C2 VARCHAR2(10),
C3 VARCHAR2(10));
INSERT INTO T_COL_ROW VALUES (1, 'v11', 'v21', 'v31');
INSERT INTO T_COL_ROW VALUES (2, 'v12', 'v22', NULL);
INSERT INTO T_COL_ROW VALUES (3, 'v13', NULL, 'v33');
INSERT INTO T_COL_ROW VALUES (4, NULL, 'v24', 'v34');
INSERT INTO T_COL_ROW VALUES (5, 'v15', NULL, NULL);
INSERT INTO T_COL_ROW VALUES (6, NULL, NULL, 'v35');
INSERT INTO T_COL_ROW VALUES (7, NULL, NULL, NULL);
COMMIT;
SELECT * FROM T_COL_ROW;
CREATE TABLE T_STR_COL AS
SELECT ID,C1||','||C2||','||C3 AS C123
FROM T_COL_ROW;
SELECT * FROM T_STR_COL;
SELECT ID,
C123,
SUBSTR(C123, 1, INSTR(C123 || ',', ',', 1, 1) - 1) C1,
SUBSTR(C123,
INSTR(C123 || ',', ',', 1, 1) + 1,
INSTR(C123 || ',', ',', 1, 2) - INSTR(C123 || ',', ',', 1, 1) - 1) C2,
SUBSTR(C123,
INSTR(C123 || ',', ',', 1, 2) + 1,
INSTR(C123 || ',', ',', 1, 3) - INSTR(C123 || ',', ',', 1, 2) - 1) C3
FROM T_STR_COL
ORDER BY 1;
6、字符串轉換成多行
示例代碼以下所示:
CREATE TABLE T_STR_ROW AS
SELECT ID,
MAX(DECODE(RN, 1, COL, NULL)) ||
MAX(DECODE(RN, 2, ',' || COL, NULL)) ||
MAX(DECODE(RN, 3, ',' || COL, NULL)) STR
FROM (SELECT ID,
COL,
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY COL) AS RN
FROM T_ROW_STR) T
GROUP BY ID
ORDER BY 1;
SELECT * FROM T_STR_ROW;
SELECT ID,
1 AS P,
SUBSTR(STR, 1, INSTR(STR || ',', ',', 1, 1) - 1) AS CV
FROM T_STR_ROW
UNION ALL
SELECT ID,
2 AS P,
SUBSTR(STR,
INSTR(STR || ',', ',', 1, 1) + 1,
INSTR(STR || ',', ',', 1, 2) - INSTR(STR || ',', ',', 1, 1) - 1) AS CV
FROM T_STR_ROW
UNION ALL
SELECT ID,
3 AS P,
SUBSTR(STR,
INSTR(STR || ',', ',', 1, 1) + 1,
INSTR(STR || ',', ',', 1, 2) - INSTR(STR || ',', ',', 1, 1) - 1) AS CV
FROM T_STR_ROW
ORDER BY 1,
2;
還有幾類特殊的轉換,以下所示:
CREATE OR REPLACE TYPE INS_SEQ_TYPE IS VARRAY(8) OF NUMBER;
SELECT * FROM TABLE(INS_SEQ_TYPE(1, 2, 3, 4, 5));
結果:
COLUMN_VALUE
------------
1
2
3
4
5
如果字符串類型,則以下所示:
CREATE OR REPLACE TYPE INS_SEQ_TYPE2 IS VARRAY(80) OF VARCHAR2(32767);
SELECT * FROM TABLE(INS_SEQ_TYPE2('aadf,dea','cbc','d'));
結果:
COLUMN_VALUE
-----------------
aadf,dea
cbc
d
還有以下的形式:
先建立一個TYPE類型,代碼以下:
CREATE OR REPLACE TYPE TYPE_STR_LHR IS TABLE OF VARCHAR2(32767);
再建立FUN_SPLIT2_LHR函數,代碼以下:
CREATE OR REPLACE FUNCTION FUN_SPLIT2_LHR(P_STR VARCHAR2,
V_SPLIT VARCHAR2 DEFAULT ',') RETURN TYPE_STR_LHR IS
RS TYPE_STR_LHR := TYPE_STR_LHR();
V_STR VARCHAR2(4000) := '';
V_LEN NUMBER := 0;
BEGIN
V_STR := P_STR;
V_LEN := LENGTH(V_SPLIT);
WHILE LENGTH(V_STR) > 0 LOOP
IF INSTR(V_STR, V_SPLIT) > 0 THEN
RS.EXTEND;
RS(RS.COUNT) := SUBSTR(V_STR, 1, INSTR(V_STR, V_SPLIT) - 1);
V_STR := SUBSTR(V_STR, INSTR(V_STR, V_SPLIT) + V_LEN);
ELSE
RS.EXTEND;
RS(RS.COUNT) := V_STR;
EXIT;
END IF;
END LOOP;
RETURN RS;
END;
測試以下:
SQL> SELECT COLUMN_VALUE FROM TABLE(FUN_SPLIT2_LHR('101,102,103',','));
COLUMN_VALUE
------------------
101
102
103
SQL> SELECT TO_NUMBER(COLUMN_VALUE) FROM TABLE(FUN_SPLIT2_LHR('101,102,103'));
TO_NUMBER(COLUMN_VALUE)
-----------------------
101
102
103
SQL> SELECT COLUMN_VALUE FROM TABLE(FUN_SPLIT2_LHR('101@#102@#103','@#'));
COLUMN_VALUE
---------------
101
102
103
& 說明:
有關行列互換更多的案例能夠參考個人BLOG:http://blog.itpub.net/26736162/viewspace-1272538/
本文選自《Oracle程序員面試筆試寶典》,做者:李華榮。
詳細內容能夠添加麥老師微信或QQ私聊。
● 本文做者:小麥苗,只專一於數據庫的技術,更注重技術的運用
● 做者博客地址:http://blog.itpub.net/26736162/abstract/1/
● 本系列題目來源於做者的學習筆記,部分整理自網絡,如有侵權或不當之處還請諒解
● 版權全部,歡迎分享本文,轉載請保留出處
● QQ:646634621 QQ羣:618766405
● 提供OCP、OCM和高可用部分最實用的技能培訓
● 題目解答如有不當之處,還望各位朋友批評指正,共同進步
長按下圖識別二維碼或微信掃描下圖二維碼來關注小麥苗的微信公衆號:xiaomaimiaolhr,學習最實用的數據庫技術。
本文分享自微信公衆號 - DB寶(lhrdba)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。