日期:2014-05-16 浏览次数:20590 次
oracle行列转换总结
最近论坛很多人提的问题都与行列转换有关系,所以我对行列转换的相关知识做了一个总结,
希望对大家有所帮助,同时有何错疏,恳请大家指出,
我也是在写作过程中学习,算是一起和大家学习吧。
行列转换包括以下六种情况:
*列转行
*行转列
*多列转换成字符串
*多行转换成字符串
*字符串转换成多列
*字符串转换成多行
下面分别进行举例介绍。
首先声明一点,有些例子需要如下10g及以后才有的知识:
a。掌握model子句,
b。正则表达式
c。加强的层次查询
讨论的适用范围只包括8i,9i,10g及以后版本。begin:
1、列转行
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;
1)UNION ALL
适用范围:8i,9i,10g及以后版本
SELECT id, 'c1' cn, c1 cv
? FROM t_col_row
UNION ALL
SELECT id, 'c2' cn, c2 cv
? FROM t_col_row
UNION ALL
SELECT id, 'c3' cn, c3 cv FROM t_col_row;
若空行不需要转换,只需加一个where条件,
WHERE COLUMN IS NOT NULL 即可。
2)MODEL
适用范围:10g及以后
SELECT id, cn, cv FROM t_col_row
MODEL
RETURN UPDATED ROWS
PARTITION BY (ID)
DIMENSION BY (0 AS n)
MEASURES ('xx' AS cn,'yyy' AS cv,c1,c2,c3)
RULES UPSERT ALL
(
? cn[1] = 'c1',
? cn[2] = 'c2',
? cn[3] = 'c3',
? cv[1] = c1[0],
? cv[2] = c2[0],
? cv[3] = c3[0]
? )
ORDER BY ID,cn;
3)collection
适用范围:8i,9i,10g及以后版本
要创建一个对象和一个集合:
CREATE TYPE cv_pair AS OBJECT(cn VARCHAR2(10),cv VARCHAR2(10));
CREATE TYPE cv_varr AS VARRAY(8) OF cv_pair;
SELECT id, t.cn AS cn, t.cv AS cv
? FROM t_col_row,
?????? TABLE(cv_varr(cv_pair('c1', t_col_row.c1),
???????????????????? cv_pair('c2', t_col_row.c2),
???????????????????? cv_pair('c3', t_col_row.c3))) t
ORDER BY 1, 2;
2、行转列
CREATE TABLE t_row_col AS
SELECT id, 'c1' cn, c1 cv
? FROM t_col_row
UNION ALL
SELECT id, 'c2' cn, c2 cv
? FROM t_col_row
UNION ALL
SELECT id, 'c3' cn, c3 cv FROM t_col_row;
SELECT * FROM t_row_col ORDER BY 1,2;
1)AGGREGATE FUNCTION
适用范围:8i,9i,10g及以后版本
SELECT id,
?????? MAX(decode(cn, 'c1', cv, NULL)) AS c1,
?????? MAX(decode(cn, 'c2', cv, NULL)) AS c2,
?????? MAX(decode(cn, 'c3', cv, NULL)) AS c3
? FROM t_row_col
GROUP BY id
ORDER BY 1;
MAX聚集函数也可以用sum、min、avg等其他聚集函数替代。
被指定的转置列只能有一列,但固定的列可以有多列,请看下面的例子:
SELECT mgr, deptno, empno, ename FROM emp ORDER BY 1, 2;
SELECT mgr,
?????? deptno,
?????? MAX(decode(empno, '7788', ename, NULL)) "7788",
?????? MAX(decode(empno, '7902', ename, NULL)) "7902",
?????? MAX(decode(empno, '7844', ename, NULL)) "7844",
?????? MAX(decode(empno, '7521', ename, NULL)) "7521",
?????? MAX(decode(empno, '7900', ename, NULL)) "7900",
?????? MAX(decode(empno, '7499', ename, NULL)) "7499",
?????? MAX(decode(empno, '7654', ename, NULL)) "7654"
? FROM emp
WHERE mgr IN (7566, 7698)
?? AND deptno IN (20, 30)
GROUP BY mgr, deptno
ORDER BY 1, 2;
这里转置列为empno,固定列为mgr,deptno。
还有一种行转列的方式,就是相同组中的行值变为单个列值,但转置的行值不变为列名:
ID??????? CN_1??????? CV_1??????? CN_2??????? CV_2??????? CN_3??????? CV_3
1??????????????? c1??????????????? v11??????????????? c2??????????????? v21??????????????? c3??????????????? v31
2??????????????? c1??????????????? v12??????????????? c2??????????????? v22??????????????? c3???????????????
3??????????????? c1??????????????? v13??????????????? c2??????????????????????????????????????? c3??????????????? v33
4??????????????? c1??????????????????????????????????????? c2??????????????? v24??????????????? c3??????????????? v34
5??????????????? c1??????????????? v15??????????????? c2??????????????????????????????????????? c3???????????????
6??????????????? c1???????????????????????