copyEmp
deptNO empNO sal
------ ----- -----
10 7782 2450
10 7839 5000
10 7934 1300
20 7369 800
20 7566 2975
20 7788 3000
20 7876 1100
20 7902 3000
30 7499 1600
30 7521 1250
30 7654 1250
30 7698 2850
30 7844 1500
30 7900 950
deptNOごとのsalのTotalと、GrandTotalを
以下の形式で求める。
出力結果
descr deptNO empNO sal
------------------- ------ ----- -----
10 7782 2450
10 7839 5000
10 7934 1300
Total Of dept - 10 10 null 8750
20 7369 800
20 7566 2975
20 7788 3000
20 7876 1100
20 7902 3000
Total Of dept - 20 20 null 10875
30 7499 1600
30 7521 1250
30 7654 1250
30 7698 2850
30 7844 1500
30 7900 950
Total Of dept - 30 30 null 9400
Grand Total of dept null null 29025
create table copyEmp as select deptNO,empNO,sal from scott.emp;
col descr for a20
--■■■rollupを使う方法■■■
select case grouping_ID(deptno, empno)
when 0+1 then 'Total Of dept - ' || deptno
when 2+1 then 'Grand Total of dept'
else ' ' end descr,
deptno,empno,sum(sal) as sal
from copyEmp
group by rollup(deptno, empno)
order by deptno, empno;
--■■■model句を使う方法1(10g以降)■■■
select descr,deptno,empno,sal
from copyEmp
model
dimension by(RowNum as rn,deptno)
measures(cast(' ' as varChar2(20)) as descr,empno,sal)
rules(
upsert all descr[0,any] = 'Total Of dept - ' || cv(deptno),
descr[null,null] = 'Grand Total of dept',
sal[null,null] = sum(sal)[any,any],
sal[0,any] order by rn,deptno = sum(sal)[any,cv()])
order by deptno,empno;
--■■■model句を使う方法2(10g以降)■■■
select descr,deptno,empno,sal
from copyEmp
model
dimension by(RowNum as rn,deptno)
measures(cast(' ' as varChar2(20)) as descr,empno,sal)
rules(
upsert all descr[0,any] = 'Total Of dept - ' || cv(deptno),
descr[null,null] = 'Grand Total of dept',
sal[0,any] order by rn,deptno = sum(sal)[any,cv()],
sal[null,null] = sum(sal)[0,any])
order by deptno,empno;
単純case式は、条件式の2度書きを防ぐといった用途に使えます。 grouping_ID関数の結果である、 grouping_ID(deptno, empno) は 0+1 2+1 のように記述すると読みやすいです。 rollupを使わずに、model句でも可能です。 パーティションを切ると最後にsumで集計できなくなることに注意です。 model句を使う方法1よりも、 model句を使う方法2のほうが導出順序が分かりやすいでしょう。 3-42 rollUpで各値と小計と総合計も表示