Oralce高级sql之rollup与cube(一)

2015-01-27 18:13:48 · 作者: · 浏览: 56
在 oracle sql 查询中,oracle 提供了一些高级功能能够简化 sql 查询语句以及提高查询性能。下面将介绍 rollup,cube的用法与区别。

1. rollup


rollup 能够在 select 语句中计算指定分组字段的多个层次的小计以及合计. rollup 非常容易使用并且非常高效。
rollup 从右到左扫描分组字段, 逐步创建更高级别的小计. 最后再创建一行总计. rollup 将创建 n + 1 个层次(级别)的小计, n 指的是 rollup 中的字段数.




1.1 什么时候使用 rollup
对于一些层次维度的小计(统计某些层次字段的小计及总计) 对于数据仓库中的统计汇总表, rollup 能够简化统计汇总表并且提高查询统计汇总表的速度
1.2 rollup 例子

?

首先构造两个基本表 emp(员工表) 与 dept(部门表):

SQL> create table emp as select * from scott.emp;

Table created.

SQL> create table dept as select * from scott.dept;

Table created.

SQL> select * from emp;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 17-DEC-80        800                    20
      7499 ALLEN      SALESMAN        7698 20-FEB-81       1600        300         30
      7521 WARD       SALESMAN        7698 22-FEB-81       1250        500         30
      7566 JONES      MANAGER         7839 02-APR-81       2975                    20
      7654 MARTIN     SALESMAN        7698 28-SEP-81       1250       1400         30
      7698 BLAKE      MANAGER         7839 01-MAY-81       2850                    30
      7782 CLARK      MANAGER         7839 09-JUN-81       2450                    10
      7788 SCOTT      ANALYST         7566 19-APR-87       3000                    20
      7839 KING       PRESIDENT            17-NOV-81       5000                    10
      7844 TURNER     SALESMAN        7698 08-SEP-81       1500          0         30
      7876 ADAMS      CLERK           7788 23-MAY-87       1100                    20
      7900 JAMES      CLERK           7698 03-DEC-81        950                    30
      7902 FORD       ANALYST         7566 03-DEC-81       3000                    20
      7934 MILLER     CLERK           7782 23-JAN-82       1300                    10

14 rows selected.

SQL> select * from dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

如果想统计每个部门每个职位的总薪水,sql 语句如下:

SQL> select b.dname, a.job, sum(a.sal)
  2  from emp a, dept b
  3  where a.deptno = b.deptno
  4  group by b.dname, a.job;

DNAME          JOB       SUM(A.SAL)
-------------- --------- ----------
SALES          MANAGER         2850
SALES          CLERK            950
ACCOUNTING     MANAGER         2450
ACCOUNTING     PRESIDENT       5000
ACCOUNTING     CLERK           1300
SALES          SALESMAN        5600
RESEARCH       MANAGER         2975
RESEARCH       ANALYST         6000
RESEARCH       CLERK           1900

9 rows selected.

如果想用一条 sql 语句统计 每个部门每个职位的总薪水每个部门的总薪水以及 所有部门的总薪水的话,势必要再用一个 group by 语句统计每个部门的总薪水然后再与上面的结果 union 起来才能得到最后的结果,但是这样写的话除了书写会复杂一点外,另外肯定还要多扫描几次 emp 与 dept 表,现在 oracle 提供了 rollup 子句,我们可以先来看看 rollup 子句的结果:
SQL> select b.dname, a.job, sum(a.sal)
  2  from emp a, dept b
  3  where a.deptno = b.deptno
  4  group by rollup(b.dname, a.job);

DNAME          JOB       SUM(A.SAL)
-------------- --------- ----------
SALES          CLERK            950
SALES          MANAGER         2850
SALES          SALESMAN        5600
SALES                          9400
RESEARCH       CLERK           1900
RESEARCH       ANALYST         6000
RESEARCH       MANAGER         2975
RESEARCH                      10875
ACCOUNTING     CLERK           1300
ACCOUNTING     MANAGER         2450
ACCOUNTING     PRESIDENT       5000
ACCOUNTING                     8750
                              29025

从上面的结果中可以看出,rollup 子句会为每个部门增加一行小计以及为所有部门增加一行总计,即统计了每个部门的总薪水以及所有部门的总薪水。

通常来说,rollup 往往同 group by 语句一起使用,它是 group by 语句的一种扩展。

?

如果语句为 group by rollup(a, b),oracle 将会从右到左先对字段 a 和 b 先进行 group by,然后对字段 A 进行 group by,最后对全表进行 group by。如果语句为 group by rollup(a, b, c), oracle 将从右到左先会对字段 a 和 b 和 c 先进行 group by, 然后对字段 a 和 b 进行 group by,然后对字段 a 进行 group by,最后对全表进行 group by。

?

下面我们将演示一个 rollup 三个字段的例子:

?

SQL> select b.dname, a.job, to_char(hiredate, 'yyyy'), sum(sal)
  2  from emp a, dept b
  3  where a.deptno = b.deptno
  4  group by b.dname, a.job, to_char(hiredate, 'yyyy')
  5  order by 1, 2, 3;

DNAME          JOB       TO_C   SUM(SAL)
-------------- --------- ---- ----------
ACCOUNTING     CLERK     1982       1300
ACCOUNTING     MANAGER   1981       2450
ACCOUNTING     PRESIDENT 1981       5000
RESEARCH       ANALYST   1981       3000
RESEARCH       ANALYST   1987       3000
RE