技术开发 频道

另一种行列转置 -- 动态SQL交叉表

  【IT168技术文档】

  交叉表的概念常在SQL Server中见到,行列转置倒是数据库经常要用到的,尤其是报表。这里给出了一个Oracle的简单实现。

  原始数据:

CLASS1 CALLDATE CALLCOUNT
1 2005-08-08   40
1   2005-08-07   6
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

0
相关文章