• GROUP BY的扩展


    GROUP BY的扩展主要包括ROLLUP,CUBE,GROUPING SETS三种形式。

    ROLLUP

    rollup相对于简单的分组合计增加了小计和合计,解释起来会比较抽象,下面我们来看看具体事例。

    例1,统计不同部门工资的总和和所有部门工资的总和。

    SQL> select deptno,sum(sal) from emp group by rollup(deptno);
    
        DEPTNO   SUM(SAL)
    ---------- ----------
            10       8750
            20      10875
            30       9400
                    29025

    例2,该例中先对deptno进行分组,再对job进行分组

    SQL> select deptno,job,sum(sal) from emp group by rollup(deptno,job);
    
        DEPTNO JOB           SUM(SAL)
    ---------- --------- ----------
            10 CLERK           1300    --10号部门中JOB为CLERK的工资的总和
            10 MANAGER         2450
            10 PRESIDENT       5000
            10                 8750    --10号所有工种工资的总和
            20 CLERK           1900
            20 ANALYST         6000
            20 MANAGER         2975
            20                10875
            30 CLERK            950
            30 MANAGER         2850
            30 SALESMAN        5600
            30                 9400
                              29025   --所有部门,所有工种工资的总和
    13 rows selected.

    如果要用普通的分组函数实现,可用UNION ALL语句:

    --实现单个部门,单个工种的工资的总和
    select
    deptno,job,sum(sal) from emp group by deptno,job union all
    --实现单个部门工资的总和
    select deptno,null,sum(sal) from emp group by deptno union all
    --实现所有部门工资的总和
    select null,null,sum(sal) from emp order by 1,2

    下面我们分别来看看两者的执行计划及统计信息,

    ROLLUP语句:

    Execution Plan
    -----------------------------------------------------------------------------
    | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    -----------------------------------------------------------------------------
    |   0 | SELECT STATEMENT     |        |     11 |    132 |      3  (34)| 00:00:01 |
    |   1 |  SORT GROUP BY ROLLUP|        |     11 |    132 |      3  (34)| 00:00:01 |
    |   2 |   TABLE ACCESS FULL  |   EMP  |     14 |    168 |      2   (0)| 00:00:01 |
    -----------------------------------------------------------------------------
    Statistics
    ----------------------------------------------------------
          0  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads
          0  redo size
        895  bytes sent via SQL*Net to client
        519  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
         13  rows processed

    UNION ALL语句:

    Execution Plan
    -----------------------------------------------------------------------------
    | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    -----------------------------------------------------------------------------
    |   0 | SELECT STATEMENT     |        |     15 |    150 |      9  (34)| 00:00:01 |
    |   1 |  SORT ORDER BY       |        |     15 |    150 |      8  (75)| 00:00:01 |
    |   2 |   UNION-ALL          |        |        |        |             |          |
    |   3 |    HASH GROUP BY     |        |     11 |    132 |      3  (34)| 00:00:01 |
    |   4 |     TABLE ACCESS FULL|   EMP  |     14 |    168 |      2   (0)| 00:00:01 |
    |   5 |    HASH GROUP BY     |        |      3 |     15 |      3  (34)| 00:00:01 |
    |   6 |     TABLE ACCESS FULL|   EMP  |     14 |     70 |      2   (0)| 00:00:01 |
    |   7 |    SORT AGGREGATE    |        |      1 |      3 |             |          |
    |   8 |     TABLE ACCESS FULL|   EMP  |     14 |     42 |      2   (0)| 00:00:01 |
    -----------------------------------------------------------------------------
    
    Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 6 consistent gets 0 physical reads 0 redo size 895 bytes sent via SQL*Net to client 519 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 13 rows processed

    不难看出,相同的功能实现,ROLLUP相对于UNION ALL效率有了极大的提升。

    CUBE

    cube相对于rollup,结果输出更加详细。

    例1,在本例中还不是很明显。

    SQL> select deptno,sum(sal) from emp group by cube(deptno);
    
        DEPTNO   SUM(SAL)
    ---------- ----------
                    29025
            10       8750
            20      10875
            30       9400

    例2,相对于rollup,cube还对工种这一列进行了专门的汇总。

    SQL> select deptno,job,sum(sal) from emp group by cube(deptno,job);
    
        DEPTNO JOB           SUM(SAL)
    ---------- --------- ----------
                              29025
               CLERK           4150
               ANALYST         6000
               MANAGER         8275
               SALESMAN        5600
               PRESIDENT       5000
           10                  8750
           10  CLERK           1300
           10  MANAGER         2450
           10  PRESIDENT       5000
           20                 10875
           20  CLERK           1900
           20  ANALYST         6000
           20  MANAGER         2975
           30                  9400
           30  CLERK            950
           30  MANAGER         2850
           30  SALESMAN        5600
    18 rows selected.

    GROUPING SETS

    GROUPING SETS相对于ROLLUP和CUBE,结果是分类统计的,可读性更好一些。

    例1:

    SQL> select deptno,job,to_char(hiredate,'yyyy')hireyear,sum(sal) from emp group by grouping sets(deptno,job,to_char(hiredate,'yyyy'));
    
        DEPTNO JOB         HIRE   SUM(SAL)
    ---------- ---------   ---- ----------
               CLERK                  4150
               SALESMAN               5600
               PRESIDENT              5000
               MANAGER                8275
               ANALYST                6000
           30                         9400
           20                        10875
           10                         8750
                            1987      4100
                            1980       800
                            1982      1300
                            1981     22825

    例2:

    SQL> select deptno,job,sum(sal) from emp group by grouping sets(deptno,job);
    
        DEPTNO JOB           SUM(SAL)
    ---------- ---------   ----------
               CLERK             4150
               SALESMAN          5600
               PRESIDENT         5000
               MANAGER           8275
               ANALYST           6000
            30                   9400
            20                  10875
            10                   8750
    8 rows selected.

    对于该例,如何用UNION ALL实现呢?

    select null deptno,job,sum(sal) from emp group by job
    union all
    select deptno,null,sum(sal) from emp group by deptno;

    两者的执行计划及统计信息分别如下:

    GROUPING SETS:

    Execution Plan
    --------------------------------------------------------------------------------------------------------
    | Id  | Operation                   | Name                      | Rows  | Bytes | Cost (%CPU)| Time     |
    --------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |                           |    11 |   352 |    10  (20)| 00:00:01 |
    |   1 |  TEMP TABLE TRANSFORMATION  |                           |       |       |            |          |
    |   2 |   LOAD AS SELECT            | SYS_TEMP_0FD9D6795_E71F79 |       |       |            |          |
    |   3 |    TABLE ACCESS FULL        | EMP                       |    14 |   168 |     2   (0)| 00:00:01 |
    |   4 |   LOAD AS SELECT            | SYS_TEMP_0FD9D6796_E71F79 |       |       |            |          |
    |   5 |    HASH GROUP BY            |                           |     1 |    19 |     3  (34)| 00:00:01 |
    |   6 |     TABLE ACCESS FULL       | SYS_TEMP_0FD9D6795_E71F79 |     1 |    19 |     2   (0)| 00:00:01 |
    |   7 |   LOAD AS SELECT            | SYS_TEMP_0FD9D6796_E71F79 |       |       |            |          |
    |   8 |    HASH GROUP BY            |                           |     1 |    26 |     3  (34)| 00:00:01 |
    |   9 |     TABLE ACCESS FULL       | SYS_TEMP_0FD9D6795_E71F79 |     1 |    26 |     2   (0)| 00:00:01 |
    |  10 |   VIEW                      |                           |     1 |    32 |     2   (0)| 00:00:01 |
    |  11 |    TABLE ACCESS FULL        | SYS_TEMP_0FD9D6796_E71F79 |     1 |    32 |     2   (0)| 00:00:01 |
    --------------------------------------------------------------------------------------------------------
    Statistics
    ----------------------------------------------------------
          4  recursive calls
         24  db block gets
         17  consistent gets
          3  physical reads
       1596  redo size
        819  bytes sent via SQL*Net to client
        519  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          8  rows processed

    UNION ALL:

    ----------------------------------------------------------------------------
    | Id  | Operation           | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------
    |   0 | SELECT STATEMENT    |       |     8 |    65 |     6  (67)| 00:00:01 |
    |   1 |  UNION-ALL          |       |       |       |            |          |
    |   2 |   HASH GROUP BY     |       |     5 |    50 |     3  (34)| 00:00:01 |
    |   3 |    TABLE ACCESS FULL|  EMP  |    14 |   140 |     2   (0)| 00:00:01 |
    |   4 |   HASH GROUP BY     |       |     3 |    15 |     3  (34)| 00:00:01 |
    |   5 |    TABLE ACCESS FULL|  EMP  |    14 |    70 |     2   (0)| 00:00:01 |
    ----------------------------------------------------------------------------
    
    Statistics
    ----------------------------------------------------------
          0  recursive calls
          0  db block gets
          4  consistent gets
          0  physical reads
          0  redo size
        819  bytes sent via SQL*Net to client
        519  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          8  rows processed

    和rollup不同的是,grouping sets的效率竟然比同等功能的union all语句低,这实现有点出乎意料。看来,也不可盲目应用Oracle提供的方案,至少,在本例中是如此。

  • 相关阅读:
    ajax跨域名
    js(鼠标键盘拖动事件)
    关于servlet转发和重新定向
    ztree的异步加载
    关于三层(dao,serviece,servlet)
    serclet监听器
    servlet(2)response常用方法
    servlet(1)request常用方法
    .post
    A1146 Topological Order
  • 原文地址:https://www.cnblogs.com/ivictor/p/4660984.html
Copyright © 2020-2023  润新知