【IT168技术文档】
交叉表的概念常在SQL Server中见到,行列转置倒是数据库经常要用到的,尤其是报表。这里给出了一个Oracle的简单实现。
原始数据:
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 |
转置后:
CALLDATE | CallCount1 | CallCount2 | CallCount3 |
2005-08-09 | 0 | 0 | 33 |
2005-08-08 | 40 | 77 | 9 |
2005-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_getrecord IS TYPE myrctype IS REF CURSOR; END pkg_getrecord; /
3. 建立动态SQL交叉表函数,输出结果集
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. 测试在SQL plus下执行:
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 |