扩展group by语句

学习自《剑破冰山 Oracle开发艺术》第五章 报表开发之扩展GROUP BY

对于简单group by语句很难对复杂维度进行分析,难以达到实际生产的复杂报表需求,group by的扩展特性就需要了,union语句也可以达到需求但是sql复杂且效率低

1 rollup多维汇总

rollup,分组先进行常规分组,然后在此基础上,通过将列从右向左移动,然后进行更高一级的小计,最后合计,注意rollup分组和列的顺序相关

指定n列,有n+1种分组方式

部分rollup可以剔除某些不需要的小计和合计

例子

[[email protected] ~]$ sqlplus scott/tiger;

SQL*Plus: Release 11.2.0.4.0 Production on Mon Mar 23 10:31:24 2020

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

10:31:24 [email protected]> set autotrace on
10:31:30 [email protected]> SELECT a.dname,b.job,SUM(b.sal) sum_sal FROM dept a,emp b WHERE a.deptno=b.deptno GROUP BY ROLLUP(a.dname,b.job);

DNAME          JOB          SUM_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

13 rows selected.

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
Plan hash value: 3067950682

-----------------------------------------------------------------------------------------
| Id  | Operation                     | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |         |    14 |   392 |     7  (29)| 00:00:01 |
|   1 |  SORT GROUP BY ROLLUP         |         |    14 |   392 |     7  (29)| 00:00:01 |
|   2 |   MERGE JOIN                  |         |    14 |   392 |     6  (17)| 00:00:01 |
|   3 |    TABLE ACCESS BY INDEX ROWID| DEPT    |     4 |    52 |     2   (0)| 00:00:01 |
|   4 |     INDEX FULL SCAN           | PK_DEPT |     4 |       |     1   (0)| 00:00:01 |
|*  5 |    SORT JOIN                  |         |    14 |   210 |     4  (25)| 00:00:01 |
|   6 |     TABLE ACCESS FULL         | EMP     |    14 |   210 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - access("A"."DEPTNO"="B"."DEPTNO")
       filter("A"."DEPTNO"="B"."DEPTNO")

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          8  consistent gets
          0  physical reads
          0  redo size
        913  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
         13  rows processed

10:31:34 [email protected]>

可以看出仅仅dept和emp表均仅扫描一次,而如果是union来写就会多次重复扫描,效率低

通过执行计划看到有个隐藏操作SORT GROUP BY ROLLUP ,显示结果有序,一般还是要显示排序的,默认的排序不一定符合业务需求

rollup分组具有方向性

如果使用hint:expand_gset_to_union,则优化器会将rollup转换为对应的union all操作,其他的grouping sets、cube也可以

部分rollup分组,将不需要小计的列从rollup拿出到group by中即可,当然合计也没有了

例子

10:31:34 [email protected]> set autotrace off
10:43:49 [email protected]> SELECT to_char(b.hiredate,‘yyyy‘) hire_year,a.dname,b.job,SUM(b.sal) sum_sal FROM dept a,emp b WHERE a.deptno=b.deptno GROUP BY to_char(b.hiredate,‘yyyy‘),a.dname,ROLLUP(b.job);

HIRE DNAME          JOB          SUM_SAL
---- -------------- --------- ----------
1980 RESEARCH       CLERK            800
1980 RESEARCH                        800
1981 SALES          CLERK            950
1981 SALES          MANAGER         2850
1981 SALES          SALESMAN        5600
1981 SALES                          9400
1981 RESEARCH       ANALYST         3000
1981 RESEARCH       MANAGER         2975
1981 RESEARCH                       5975
1981 ACCOUNTING     MANAGER         2450
1981 ACCOUNTING     PRESIDENT       5000
1981 ACCOUNTING                     7450
1982 ACCOUNTING     CLERK           1300
1982 ACCOUNTING                     1300
1987 RESEARCH       CLERK           1100
1987 RESEARCH       ANALYST         3000
1987 RESEARCH                       4100

17 rows selected.

Elapsed: 00:00:00.01
10:43:53 [email protected]>

2 cube交叉报表

cube分组可以实现更精细复杂的统计,对不同维度的所以可能进行分析,生成交叉报表,cube分组,是从n列中先进行合计,即一个列不取,然后小计,即取1列到n-1列,最后n列全取,即标准分组

因为包含所有可能的组合,所以结果与列的顺序无关,列顺序仅仅影响默认的隐藏排序而已,如果用了显示排序则无所谓了

cube分组增加一列,可能结果是指数级的增长,分组种类2的n次方

语法类似,例子

11:02:40 [email protected]> set autotrace on
11:02:48 [email protected]>  SELECT a.dname,b.job,SUM(b.sal) sum_sal FROM dept a,emp b WHERE a.deptno=b.deptno GROUP BY CUBE(a.dname,b.job);

DNAME          JOB          SUM_SAL
-------------- --------- ----------
                              29025
               CLERK           4150
               ANALYST         6000
               MANAGER         8275
               SALESMAN        5600
               PRESIDENT       5000
SALES                          9400
SALES          CLERK            950
SALES          MANAGER         2850
SALES          SALESMAN        5600
RESEARCH                      10875
RESEARCH       CLERK           1900
RESEARCH       ANALYST         6000
RESEARCH       MANAGER         2975
ACCOUNTING                     8750
ACCOUNTING     CLERK           1300
ACCOUNTING     MANAGER         2450
ACCOUNTING     PRESIDENT       5000

18 rows selected.

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
Plan hash value: 2382666110

-------------------------------------------------------------------------------------------
| Id  | Operation                       | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |         |    14 |   392 |     7  (29)| 00:00:01 |
|   1 |  SORT GROUP BY                  |         |    14 |   392 |     7  (29)| 00:00:01 |
|   2 |   GENERATE CUBE                 |         |    14 |   392 |     7  (29)| 00:00:01 |
|   3 |    SORT GROUP BY                |         |    14 |   392 |     7  (29)| 00:00:01 |
|   4 |     MERGE JOIN                  |         |    14 |   392 |     6  (17)| 00:00:01 |
|   5 |      TABLE ACCESS BY INDEX ROWID| DEPT    |     4 |    52 |     2   (0)| 00:00:01 |
|   6 |       INDEX FULL SCAN           | PK_DEPT |     4 |       |     1   (0)| 00:00:01 |
|*  7 |      SORT JOIN                  |         |    14 |   210 |     4  (25)| 00:00:01 |
|   8 |       TABLE ACCESS FULL         | EMP     |    14 |   210 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   7 - access("A"."DEPTNO"="B"."DEPTNO")
       filter("A"."DEPTNO"="B"."DEPTNO")

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          8  consistent gets
          0  physical reads
          0  redo size
       1175  bytes sent via SQL*Net to client
        535  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          3  sorts (memory)
          0  sorts (disk)
         18  rows processed

11:02:52 [email protected]>

可以看执行计划,结果也是有序的

部分cube分组,例子

11:06:24 [email protected]>  SELECT a.dname,b.job,SUM(b.sal) sum_sal FROM dept a,emp b WHERE a.deptno=b.deptno GROUP BY a.dname,CUBE(b.job);

DNAME          JOB          SUM_SAL
-------------- --------- ----------
SALES                          9400
SALES          CLERK            950
SALES          MANAGER         2850
SALES          SALESMAN        5600
RESEARCH                      10875
RESEARCH       CLERK           1900
RESEARCH       ANALYST         6000
RESEARCH       MANAGER         2975
ACCOUNTING                     8750
ACCOUNTING     CLERK           1300
ACCOUNTING     MANAGER         2450
ACCOUNTING     PRESIDENT       5000

12 rows selected.

Elapsed: 00:00:00.00
11:06:26 [email protected]>

3 grouping sets实现小计

rollup和cube会产生各种标准分组、小计、合计,grouping  sets则只关注指定维度的小计,n列的结果也是n种

如grouping sets(a,b,c)就是group by a、group by b和group by c的结果union all

例子

11:06:26 [email protected]>  set autotrace on
11:12:33 [email protected]> SELECT to_char(b.hiredate,‘yyyy‘) hire_year,a.dname,b.job,SUM(b.sal) sum_sal FROM dept a,emp b WHERE a.deptno=b.deptno GROUP BY GROUPING SETS( to_char(b.hiredate,‘yyyy‘),a.dname,b.job);

HIRE DNAME          JOB          SUM_SAL
---- -------------- --------- ----------
                    CLERK           4150
                    SALESMAN        5600
                    PRESIDENT       5000
                    MANAGER         8275
                    ANALYST         6000
     ACCOUNTING                     8750
     RESEARCH                      10875
     SALES                          9400
1987                                4100
1980                                 800
1982                                1300
1981                               22825

12 rows selected.

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
Plan hash value: 2825031421

------------------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name                      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                           |    14 |   448 |    17  (24)| 00:00:01 |
|   1 |  TEMP TABLE TRANSFORMATION     |                           |       |       |            |          |
|   2 |   LOAD AS SELECT               | SYS_TEMP_0FD9D660D_29B9BB |       |       |            |          |
|   3 |    MERGE JOIN                  |                           |    14 |   504 |     6  (17)| 00:00:01 |
|   4 |     TABLE ACCESS BY INDEX ROWID| DEPT                      |     4 |    52 |     2   (0)| 00:00:01 |
|   5 |      INDEX FULL SCAN           | PK_DEPT                   |     4 |       |     1   (0)| 00:00:01 |
|*  6 |     SORT JOIN                  |                           |    14 |   322 |     4  (25)| 00:00:01 |
|   7 |      TABLE ACCESS FULL         | EMP                       |    14 |   322 |     3   (0)| 00:00:01 |
|   8 |   LOAD AS SELECT               | SYS_TEMP_0FD9D660E_29B9BB |       |       |            |          |
|   9 |    HASH GROUP BY               |                           |     5 |    60 |     3  (34)| 00:00:01 |
|  10 |     TABLE ACCESS FULL          | SYS_TEMP_0FD9D660D_29B9BB |    14 |   168 |     2   (0)| 00:00:01 |
|  11 |   LOAD AS SELECT               | SYS_TEMP_0FD9D660E_29B9BB |       |       |            |          |
|  12 |    HASH GROUP BY               |                           |     4 |    56 |     3  (34)| 00:00:01 |
|  13 |     TABLE ACCESS FULL          | SYS_TEMP_0FD9D660D_29B9BB |    14 |   196 |     2   (0)| 00:00:01 |
|  14 |   LOAD AS SELECT               | SYS_TEMP_0FD9D660E_29B9BB |       |       |            |          |
|  15 |    HASH GROUP BY               |                           |     1 |     8 |     3  (34)| 00:00:01 |
|  16 |     TABLE ACCESS FULL          | SYS_TEMP_0FD9D660D_29B9BB |    14 |   112 |     2   (0)| 00:00:01 |
|  17 |   VIEW                         |                           |     5 |   160 |     2   (0)| 00:00:01 |
|  18 |    TABLE ACCESS FULL           | SYS_TEMP_0FD9D660E_29B9BB |     5 |    60 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   6 - access("SYS_TBL_$2$"."DEPTNO"="SYS_TBL_$1$"."DEPTNO")
       filter("SYS_TBL_$2$"."DEPTNO"="SYS_TBL_$1$"."DEPTNO")

Statistics
----------------------------------------------------------
         23  recursive calls
         33  db block gets
         39  consistent gets
          4  physical reads
       2172  redo size
        962  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
         12  rows processed

11:12:36 [email protected]>

执行计划可以看出,没有默认排序了,无序,和列的顺序也无关

同理部分grouping sets分组,例子

11:12:36 [email protected]> set autotrace off
11:17:03 [email protected]> SELECT a.dname,to_char(b.hiredate,‘yyyy‘) hire_year,b.job,SUM(b.sal) sum_sal FROM dept a,emp b WHERE a.deptno=b.deptno GROUP BY a.dname,GROUPING SETS(to_char(b.hiredate,‘yyyy‘),b.job);

DNAME          HIRE JOB          SUM_SAL
-------------- ---- --------- ----------
SALES               MANAGER         2850
SALES               CLERK            950
ACCOUNTING          MANAGER         2450
ACCOUNTING          PRESIDENT       5000
ACCOUNTING          CLERK           1300
RESEARCH            MANAGER         2975
SALES               SALESMAN        5600
RESEARCH            ANALYST         6000
RESEARCH            CLERK           1900
RESEARCH       1981                 5975
SALES          1981                 9400
RESEARCH       1987                 4100
ACCOUNTING     1981                 7450
ACCOUNTING     1982                 1300
RESEARCH       1980                  800

15 rows selected.

Elapsed: 00:00:00.01
11:17:05 [email protected]>

注意此时的含义有较大的变化

cube、rollup作为grouping sets的参数

grouping sets只提供单列分组,没有合计功能,如果需要提供合计,则可以将rollup或cube作为参数,例子

11:23:59 [email protected]>  SELECT a.dname,b.job,SUM(b.sal) sum_sal FROM dept a,emp b WHERE a.deptno=b.deptno GROUP BY GROUPING sets(rollup(a.dname),ROLLUP(b.job));

DNAME          JOB          SUM_SAL
-------------- --------- ----------
               CLERK           4150
               SALESMAN        5600
               PRESIDENT       5000
               MANAGER         8275
               ANALYST         6000
ACCOUNTING                     8750
RESEARCH                      10875
SALES                          9400
                              29025
                              29025

10 rows selected.

Elapsed: 00:00:00.02
11:24:02 [email protected]>

问题是产生了两个合计行,因为rollup或cube作为grouping sets参数,相当于每个rollup或cube操作的union all,等价于这就很好理解功能了

对于重复合计,使用distinct剔除即可,另外后面还有特殊的函数可以使用,group_id可以用来剔除重复分组(和distinct功能是不一样的)

rollup和cube作为参数也可以混用,而且也可以使用其它扩展功能,如部分分组、复合列分组、连接分组等

rollup和cube不能接受grouping sets作为参数,rollup和cube互相作为参数也不行

4 组合列分组、连接分组、重置列分组

组合列分组、连接分组在复杂报表中用处很大。组合列分组用于剔除不必要的小计保留合计,连接分组按每个分组的笛卡尔积进行操作,分组更多更细。对于常规分组满足不了的需求可以考虑

组合列即将多个列当做整体对待,下列对比表可以清晰展示不同之处

连接分组更强大,允许group by后出现多个rollup、cube和grouping sets操作,这样分组级别更多,报表更精细,实现很复杂的需求实际上不管是同类型的连接分组还是不通类型的连接分组之间,最后的分组级别种类都是每个扩展分组级别种类的乘积,分组级别是笛卡尔积,比如rollup(a,b),rollup(c),最终3*2=6中分组级别

重复列分组也就是group by中允许重复列,比如group by rollup(a,(a,b))、group by a,rollup(a,b)

组合列分组

例子

14:48:13 [email protected]> SELECT a.dname,to_char(b.hiredate,‘yyyy‘) hire_year,b.job,SUM(b.sal) sum_sal FROM dept a,emp b WHERE a.deptno=b.deptno GROUP BY rollup(a.dname,(to_char(b.hiredate,‘yyyy‘),b.job));

DNAME          HIRE JOB          SUM_SAL
-------------- ---- --------- ----------
SALES          1981 CLERK            950
SALES          1981 MANAGER         2850
SALES          1981 SALESMAN        5600
SALES                               9400
RESEARCH       1980 CLERK            800
RESEARCH       1981 ANALYST         3000
RESEARCH       1981 MANAGER         2975
RESEARCH       1987 CLERK           1100
RESEARCH       1987 ANALYST         3000
RESEARCH                           10875
ACCOUNTING     1981 MANAGER         2450
ACCOUNTING     1981 PRESIDENT       5000
ACCOUNTING     1982 CLERK           1300
ACCOUNTING                          8750
                                   29025

15 rows selected.

Elapsed: 00:00:00.00
14:48:16 [email protected]>

组合列分组可以实现部分rollup和部分cube分组类似效果并且加上合计

但是这个也比较麻烦,对于需要cube、rollup合计并剔除部分小计的需求用grouping_id或grouping函数

cube和rollup均可以转换为对应的grouping sets

当然反向也可以,不过意义不大

连接分组

例子

14:48:16 [email protected]>  SELECT a.dname,to_char(b.hiredate,‘yyyy‘) hire_year,b.job,SUM(b.sal) sum_sal FROM dept a,emp b WHERE a.deptno=b.deptno GROUP BY rollup(a.dname,b.job),ROLLUP(to_char(b.hiredate,‘yyyy‘));

DNAME          HIRE JOB          SUM_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
RESEARCH       1980 CLERK            800
RESEARCH       1980                  800
               1980                  800
SALES          1981 CLERK            950
SALES          1981 MANAGER         2850
SALES          1981 SALESMAN        5600
SALES          1981                 9400
RESEARCH       1981 ANALYST         3000
RESEARCH       1981 MANAGER         2975
RESEARCH       1981                 5975
ACCOUNTING     1981 MANAGER         2450
ACCOUNTING     1981 PRESIDENT       5000
ACCOUNTING     1981                 7450
               1981                22825
ACCOUNTING     1982 CLERK           1300
ACCOUNTING     1982                 1300
               1982                 1300
RESEARCH       1987 CLERK           1100
RESEARCH       1987 ANALYST         3000
RESEARCH       1987                 4100
               1987                 4100

34 rows selected.

Elapsed: 00:00:00.01
14:57:57 [email protected]>

相当于两个rollup的笛卡尔积

理解了之后,利用连接分组,cube可以用rollup转换,如cube(a,b,c)等于rollup(a),rollup(b),rollup(c),但是对于rollup和grouping sets转换为cube一般没啥用

连接分组一般是同类型的,不通类型的连接分组一般不常用

重复列分组

例子

14:57:57 [email protected]>   SELECT a.dname,b.job,SUM(b.sal) sum_sal FROM dept a,emp b WHERE a.deptno=b.deptno GROUP BY a.dname,ROLLUP(a.dname,b.job);

DNAME          JOB          SUM_SAL
-------------- --------- ----------
SALES          CLERK            950
SALES          MANAGER         2850
SALES          SALESMAN        5600
RESEARCH       CLERK           1900
RESEARCH       ANALYST         6000
RESEARCH       MANAGER         2975
ACCOUNTING     CLERK           1300
ACCOUNTING     MANAGER         2450
ACCOUNTING     PRESIDENT       5000
SALES                          9400
RESEARCH                      10875
ACCOUNTING                     8750
SALES                          9400
RESEARCH                      10875
ACCOUNTING                     8750

15 rows selected.

Elapsed: 00:00:00.00
15:07:14 [email protected]>

没啥意义的例子,只不过说明语法允许

5 三个扩展分组函数:grouping、grouping_id、group_id

三个扩展分组函数:grouping、grouping_id、group_id在生成有意义的报表、结果进行过滤、排序中有很重要的作用,常用于复杂的报表查询

注意grouping和grouping_id函数的参数不能是组合列

grouping函数用于制作有意义的报表

grouping_id函数对结果过滤以及排序

group_id函数剔除重复行

grouping函数

在扩展group by子句来说,null表示小计或者合计,但是如果数据中本来就有null值呢?grouping函数专门处理扩展group by分组中null问题:

它只接受一个参数,且参数来自rollup、cube、grouping sets中的列。当然也可以在group by而不在上述3个子句的列,不过结果肯定是0,没有意义

grouping函数对于小计或合计的列返回1,否则返回0。用于区别是否原始数据中含null,常与decode一起使用。当然也可以确定分组级别从而过滤一些行,不过会很烦,一般用grouping_id替代

例子

15:34:01 [email protected]>  SELECT decode(GROUPING(a.dname),1,‘全部部门‘,a.dname) dname,decode(grouping(b.mgr),1,‘全部老板‘,b.mgr) mgr,SUM(b.sal) sum_sal FROM dept a,emp b WHERE a.deptno=b.deptno GROUP BY ROLLUP(a.dname,b.mgr);

DNAME          MGR                                         SUM_SAL
-------------- ---------------------------------------- ----------
SALES          7698                                           6550
SALES          7839                                           2850
SALES          全部老板                                       9400
RESEARCH       7566                                           6000
RESEARCH       7788                                           1100
RESEARCH       7839                                           2975
RESEARCH       7902                                            800
RESEARCH       全部老板                                      10875
ACCOUNTING                                                    5000
ACCOUNTING     7782                                           1300
ACCOUNTING     7839                                           2450
ACCOUNTING     全部老板                                       8750
全部部门       全部老板                                      29025

13 rows selected.

Elapsed: 00:00:00.01
15:34:12 [email protected]>

grouping_id函数

用于过滤分组级别和排序结果

可以接受多个参数,来自rollup、cube、grouping sets中的列,按列从左往右顺序计算,是分组列则0,是小计或合计列为1,然后组合成为一个二进制数字叫做位向量,位向量转化为10进制即最后的结果,代表分组级别,如cube(a,b),那么grouping_id(a,b)代表的如下

grouping_id的好处是可以对多列进行计算得到分组级别

例子

15:46:26 [email protected]>  SELECT a.dname,b.mgr,b.job,SUM(b.sal) sum_sal FROM dept a,emp b WHERE a.deptno=b.deptno GROUP BY ROLLUP(a.dname,b.mgr,b.job) HAVING grouping_id(a.dname,b.mgr,b.job) IN (0,7);

DNAME                 MGR JOB          SUM_SAL
-------------- ---------- --------- ----------
SALES                7698 CLERK            950
SALES                7698 SALESMAN        5600
SALES                7839 MANAGER         2850
RESEARCH             7566 ANALYST         6000
RESEARCH             7788 CLERK           1100
RESEARCH             7839 MANAGER         2975
RESEARCH             7902 CLERK            800
ACCOUNTING                PRESIDENT       5000
ACCOUNTING           7782 CLERK           1300
ACCOUNTING           7839 MANAGER         2450
                                         29025

11 rows selected.

Elapsed: 00:00:00.00
15:46:29 [email protected]>

group_id函数

group_id无参数,因为扩展group by子句允许多种复杂分组操作,有时候为了实现复杂报表,可能出现重复统计,而group_id函数可以区分重复分组结果,第一次出现为0,以后每次出现增1,group_id在select中出现没啥意义,通常用于having子句剔除重复统计

例子

15:46:29 [email protected]>  SELECT a.dname,b.job,SUM(b.sal) sum_sal,group_id() gi FROM dept a,emp b WHERE a.deptno=b.deptno GROUP BY GROUPING SETS(ROLLUP(a.dname),ROLLUP(b.job)) HAVING group_id()=0;

DNAME          JOB          SUM_SAL         GI
-------------- --------- ---------- ----------
               CLERK           4150          0
               SALESMAN        5600          0
               PRESIDENT       5000          0
               MANAGER         8275          0
               ANALYST         6000          0
ACCOUNTING                     8750          0
RESEARCH                      10875          0
SALES                          9400          0
                              29025          0

9 rows selected.

Elapsed: 00:00:00.01
15:55:55 [email protected]>

原文地址:https://www.cnblogs.com/yongestcat/p/12550374.html

时间: 2024-08-01 19:57:18

扩展group by语句的相关文章

[Oracle] Group By 语句的扩展 - Rollup、Cube和Grouping Sets

常常写SQL语句的人应该知道Group by语句的主要使用方法是进行分类汇总,以下是一种它最常见的使用方法(依据部门.职位分别统计业绩): SELECT a.dname,b.job,SUM(b.sal) sum_sal FROM dept a,emp b WHERE a.deptno = b.deptno GROUP BY a.dname,b.job; DNAME JOB SUM_SAL -------------- --------- ---------- SALES MANAGER 2850

理解group by 语句的扩展使用

在SQL的开发中我们会经常使用group by语句对数据进行分组统计,然而在一些复杂的BI报表开发中会常遇到更复杂的分组需求,单单使用group by 就不能解决我们的问题了,这时我们就需要学习了解一下在group by 语句上的一些扩展使用,下面我们就来学习一下rollup.cube.grouping sets语句的使用. 1.group by SQL> select a.dname,b.job,sum(b.sal) sum_sal 2 from dept a,emp b 3 where a.

SQL GROUP BY 语句

合计函数 (比如 SUM) 常常需要添加 GROUP BY 语句. GROUP BY 语句 GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组. SQL GROUP BY 语法 SELECT column_name, aggregate_function(column_name) FROM table_name WHERE column_name operator value GROUP BY column_name SQL GROUP BY 实例 我们拥有下面这个 "Or

GROUP BY语句与HAVING语句的使用

一.GROUP BY GROUP BY语句用来与聚合函数(aggregate functions such as COUNT, SUM, AVG, MIN, or MAX.)联合使用来得到一个或多个列的结果集.语法如下: SELECT column1, ... column_n, aggregate_function(expression) FROM tables WHERE predicates GROUP BY column1, ... column_n; 举例 比如说我们有一个学生表格(s

5.扩展 GROUP BY

/*************************************************主题:扩展 GROUP BY CUBE ,ROLLUP,GROUPING SETS,GROUPING_ID,GROUP_ID*************************************************/ 1.ROLLUP ,按列的顺序从右到左递减分组小计(含合计)        -------------------------------------            

SQL中GROUP BY语句与HAVING语句的使用

一.GROUP BY GROUP BY语句用来与聚合函数(aggregate functions such as COUNT, SUM, AVG, MIN, or MAX.)联合使用来得到一个或多个列的结果集. 语法如下: SELECT column1, column2, ... column_n, aggregate_function (expression) FROM tables WHERE predicates GROUP BY column1, column2, ... column_

MySQL GROUP BY 语句

MySQL GROUP BY 语句 GROUP BY 语句根据一个或多个列对结果集进行分组. 在分组的列上我们可以使用 COUNT, SUM, AVG,等函数. GROUP BY 语法 SELECT column_name, function(column_name) FROM table_name WHERE column_name operator value GROUP BY column_name; 实例演示 本章节实例使用到了以下表结构及数据,使用前我们可以先将以下数据导入数据库中.

SQL-W3School-函数:SQL GROUP BY 语句

ylbtech-SQL-W3School-函数:SQL GROUP BY 语句 1.返回顶部 1. 合计函数 (比如 SUM) 常常需要添加 GROUP BY 语句. GROUP BY 语句 GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组. SQL GROUP BY 语法 SELECT column_name, aggregate_function(column_name) FROM table_name WHERE column_name operator value

GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组

1 drop table orders; 2 create table orders ( 3 o_id int auto_increment primary key, 4 orderdate date, 5 orderprice int, 6 customer varchar(100) 7 ); 8 9 insert into orders(orderdate, orderprice, customer) values('2008-12-29', 1000, 'Bush'); 10 insert