在報表的開發當中,難免會遇到行轉列的問題。
以Oracle中scott的emp為例,統計各職位的人員在各部門的人數分布情況,就可以用“行轉列”:
scott的emp的原始數據為:
EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
7369 | SMITH | CLERK | 7902 | 12/17/1980 | 800.00 | 20 | |
7499 | ALLEN | SALESMAN | 7698 | 2/20/1981 | 1600.00 | 300.00 | 30 |
7521 | WARD | SALESMAN | 7698 | 2/22/1981 | 1250.00 | 500.00 | 30 |
7566 | JONES | MANAGER | 7839 | 4/2/1981 | 2975.00 | 20 | |
7654 | MARTIN | SALESMAN | 7698 | 9/28/1981 | 1250.00 | 1400.00 | 30 |
7698 | BLAKE | MANAGER | 7839 | 5/1/1981 | 2850.00 | 30 | |
7782 | CLARK | MANAGER | 7839 | 6/9/1981 | 2450.00 | 10 | |
7788 | SCOTT | ANALYST | 7566 | 4/19/1987 | 3000.00 | 20 | |
7839 | KING | PRESIDENT | 11/17/1981 | 5000.00 | 10 | ||
7844 | TURNER | SALESMAN | 7698 | 9/8/1981 | 1500.00 | 0.00 | 30 |
7876 | ADAMS | CLERK | 7788 | 5/23/1987 | 1100.00 | 20 | |
7900 | JAMES | CLERK | 7698 | 12/3/1981 | 950.00 | 30 | |
7902 | FORD | ANALYST | 7566 | 12/3/1981 | 3000.00 | 20 | |
7934 | MILLER | CLERK | 7782 | 1/23/1982 | 1300.00 | 10 |
使用“行轉列”統計各職位的人員在各部門的分布人數后,數據為:
JOB | 10(DEPTNO) | 20(DEPTNO) | 30(DEPTNO) | 40(DEPTNO) |
CLERK | 1 | 2 | 1 | 0 |
SALESMAN | 0 | 0 | 4 | 0 |
PRESIDENT | 1 | 0 | 0 | 0 |
MANAGER | 1 | 1 | 1 | 0 |
ANALYST | 0 | 2 | 0 | 0 |
一、經典的實現方式
主要是利用decode函數、聚合函數(如max、sum等)、group by分組實現的

select t.job, count(decode(t.deptno, '10', 1)) as "10(DEPTNO)", count(decode(t.deptno, '20', 1)) as "20(DEPTNO)", count(decode(t.deptno, '30', 1)) as "30(DEPTNO)", count(decode(t.deptno, '40', 1)) as "40(DEPTNO)" from scott.emp t group by t.job;
二、PIVOT
Oracle 11g后,出現PIVOT,更簡便地實現“行轉列”。使用前,需確定數據庫環境大於11g,最好也確認下生產環境的數據庫是否大於11g,避免項目后期出現狀況。

with tmp_tab as( select t.job, t.deptno from scott.emp t ) select * from tmp_tab t pivot(count(1) for deptno in (10, 20, 30, 40));
三、PIVOT XML
使用經典的方法和PIVOT方法,DEPTNO的參數是硬編碼的。而通過PIVOT XML能解決這一問題,使分列條件可以是動態的。但,輸出的是XML的CLOB的格式。目前,Java讀取PIVOT XML CLOB貌似比較困難(本人沒有成功讀取,可見下文描述,如有知曉者,請知悉)。

with tmp_tab as( select t.job, t.deptno from scott.emp t ) select * from tmp_tab t pivot xml (count(1) for deptno in (select deptno from scott.dept));
然而,當寫完上面PIVOT XML滴時候,使用Java讀取數據時,卻發現讀取不了PIVOT XML的CLOB(普通的並且數據相同的CLOB卻能正常讀取)
努力了幾天,亦嘗試下載目前最新的OJDBC,但仍然報錯。
報錯為
- “Invalid column type: getCLOB not implemented for class oracle.jdbc.driver.T4CNamedTypeAccessor”--ojdbc6.jar