GROUP_ID

首先我们看看官方的解释:

大意是GROUP_ID用于区分相同分组标准的分组统计结果。

解释起来比较抽象,下面我们来看看具体的案例。

例1:单一分组

SQL> select group_id(),deptno,sum(sal) from emp group by rollup(deptno);

GROUP_ID()     DEPTNO    SUM(SAL)
---------- ---------- ----------
0 10 8750
0 20 10875
0 30 9400
0 29025

rollup(deptno)只是一个唯一的分组,所以产生的group_id()为0,代表这是同一个分组的结果。

下面我们来看看重复分组的情况

例2:重复分组

SQL> select group_id(),deptno,sum(sal) from emp group by rollup(deptno,deptno);

GROUP_ID()      DEPTNO    SUM(SAL)
---------- ---------- ----------
0 10 8750
0 20 10875
0 30 9400
1 10 8750
1 20 10875
1 30 9400
0 29025 7 rows selected.

group_id()为1代表这些是重复的分组。

注意:可通过having group_id() <1来剔除重复的分组。

老实说,我也看不出GROUP_ID在实际工作中的应用场景,姑且先记着。

GROUPING

其语法为:GROUPING(expr)

下面我们来看看官方的解释:

即GROUPING函数用于区分分组后的普通行和聚合行。如果是聚合行,则返回1,反之,则是0。

下面我们来看看具体的案例:

SQL> select grouping(deptno),grouping(job),deptno,job,sum(sal) from emp group by rollup(deptno,job);

GROUPING(DEPTNO) GROUPING(JOB)       DEPTNO JOB          SUM(SAL)
---------------- ------------- ---------- --------- ----------
0 0 10 CLERK 1300
0 0 10 MANAGER 2450
0 0 10 PRESIDENT 5000
0 1 10 8750
0 0 20 CLERK 1900
0 0 20 ANALYST 6000
0 0 20 MANAGER 2975
0 1 20 10875
0 0 30 CLERK 950
0 0 30 MANAGER 2850
0 0 30 SALESMAN 5600
0 1 30 9400
1 1 29025 13 rows selected.

首先我们看GROUPING(DEPTNO)这一列的结果,不难看出,凡是基于DEPTNO的汇总,GROUPING的结果均为0,因为最后一行是总的汇总,所以GROUPING的值为1.

基于这个逻辑,可以看出GROUPING(JOB)的值也是吻合的。

GROUPING_ID

GROUPING_ID是GROUPING的增强版,与GROUPING只能带一个表达式不同,它能带多个表达式。

语法如下:

GROUPING_ID(expr1, expr2, expr3,….)

下面我们来看看官方的解释:

GROUPING_ID在功能上相当于将多个GROUPING函数的结果串接成二进制数,返回的是这个二进制数对应的十进制数。

下面我们来看看具体的案例:

SQL> select grouping(deptno)g_d,grouping(job)g_j,grouping_id(deptno)gi_d,grouping_id(job)gi_j,grouping_id(deptno,job)gi_dj,grouping_id(job,deptno)gi_jd,deptno,job,sum(sal) from emp group by cube(deptno,job);

       G_D        G_J        GI_D       GI_J      GI_DJ      GI_JD    DEPTNO  JOB         SUM(SAL)
---------- ---------- ---------- ---------- ---------- ---------- ---------- --------- ----------
1 1 1 1 3 3 29025
1 0 1 0 2 1 CLERK 4150
1 0 1 0 2 1 ANALYST 6000
1 0 1 0 2 1 MANAGER 8275
1 0 1 0 2 1 SALESMAN 5600
1 0 1 0 2 1 PRESIDENT 5000
0 1 0 1 1 2 10 8750
0 0 0 0 0 0 10 CLERK 1300
0 0 0 0 0 0 10 MANAGER 2450
0 0 0 0 0 0 10 PRESIDENT 5000
0 1 0 1 1 2 20 10875
0 0 0 0 0 0 20 CLERK 1900
0 0 0 0 0 0 20 ANALYST 6000
0 0 0 0 0 0 20 MANAGER 2975
0 1 0 1 1 2 30 9400
0 0 0 0 0 0 30 CLERK 950
0 0 0 0 0 0 30 MANAGER 2850
0 0 0 0 0 0 30 SALESMAN 5600 18 rows selected.

大家看到这个案例估计都有点晕。。。

之所以这样提供,是为了呈现一个直观的结果进行对比。

解读这个结果,需要注意以下两点:

1> 若本行是某expr的汇总,那么该expr对应的二进制数位置为0否则置为1。

2> GROUPING_ID(expr1, expr2, expr3,….)的值其实是对应GROUPING(expr1),GROUPING(expr2),GROUPING(expr3)...值的串接。

首先看第一列,第三列,虽然一个是grouping(deptno),一个是grouping_id(deptno),因为只有一个表达式,所以两者的结果是一样的。第二列,第四列同样如此。

第五列的结果是第一列和第二列的数值的串接,然后返回的十进制数,以第二行为例,GI_DJ=2其实是二进制10转化为十进制后的数,其中1为G_D的值,0为G_J的值。

而GI_JD=1则是二进制01转化为十进制后的数,其中0为G_J的值,1为G_D的值。注意,串接的顺序为GROUPING_ID中表达式的顺序。

说了这么多,下面我们来看一个利用GROUPING_ID实现行列转换的案例。

with t as
( select grouping_id(deptno,job)gi_dj,deptno,job,count(*)cnt
from emp group by cube(deptno,job)),
t1 as
( select decode(gi_dj,0,deptno,1,deptno,99) deptno,decode(gi_dj,1,cnt,3,cnt)sub_total,
decode(job,'CLERK',cnt) c1,decode(job,'ANALYST',cnt)c2,decode(job,'MANAGER',cnt)c3,
decode(job,'SALESMAN',cnt)c4,decode(job,'PRESIDENT',cnt)c5
from t)
select deptno,max(sub_total) sub_total,max(c1)clerk,max(c2)analyst,
max(c3)manager,max(c4)salesman,max(c5)president
from t1 group by deptno order by deptno;

最后生成的结果如下:

    DEPTNO  SUB_TOTAL      CLERK     ANALYST    MANAGER     SALESMAN  PRESIDENT
---------- ---------- ---------- --------- ---------- ---------- ----------
10 3 1 1 1
20 5 2 2 1
30 6 1 1 4
99 14 4 2 3 4 1

其中,99代表合计,sub_total代表小计。这种统计类的需求在实际生产中还是应用蛮广的。

当然,该结果也可利用PIVOT函数实现,具体语句如下:

with t as(select grouping_id(deptno,job)gi_dj,deptno,job,count(*)cnt from emp group by cube(deptno,job)),
t1 as (select decode(gi_dj,0,deptno,1,deptno,99)deptno,decode(gi_dj,0,job,2,job,9)job,cnt from t)
select * from (select * from t1)pivot(sum(cnt)for job in ('9','CLERK','ANALYST','MANAGER','SALESMAN','PRESIDENT')) order by deptno;

参考资料:

1> http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions070.htm#SQLRF00646

2> http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions071.htm#SQLRF00647

3> http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions072.htm#SQLRF00648

GROUP函数的更多相关文章

  1. GROUP函数-GROUP_ID,GROUPING,GROUPING_ID

    GROUP_ID 首先我们看看官方的解释: 大意是GROUP_ID用于区分相同分组标准的分组统计结果. 解释起来比较抽象,下面我们来看看具体的案例. 例1:单一分组 SQL> select gr ...

  2. Oracle的 listagg() WITHIN GROUP ()函数使用

    1.使用条件查询  查询部门为20的员工列表 -- 查询部门为20的员工列表    SELECT t.DEPTNO,t.ENAME FROM SCOTT.EMP t where t.DEPTNO = ...

  3. 关于MySQL的行转列的简单应用(二)---group函数

    MySQL的行转列.列转行.连接字符串  concat.concat_ws.group_concat函数用法使用方法:CONCAT(str1,str2,…) 返回结果为连接参数产生的字符串.如有任何一 ...

  4. Java正则表达式--Matcher.group函数的用法

    原来,group是针对()来说的,group(0)就是指的整个串,group(1) 指的是第一个括号里的东西,group(2)指的第二个括号里的东西. 最近学习正则表达式,发现Java中的一些术语与其 ...

  5. MongoDB中的group

    在Mongodb的查询中,有类似于SQL中group by功能的group函数.两者的功能有些类似,但是区别也是比较明显的. 对于SQL来说,group by的作用就是安装依据列来将数据表中的记录分成 ...

  6. MongoDB学习总结(三) —— 常用聚合函数

    上一篇介绍了MongoDB增删改查命令的基本用法,这一篇来学习一下MongoDB的一些基本聚合函数. 下面我们直奔主题,用简单的实例依次介绍一下. > count() 函数 集合的count函数 ...

  7. python第六天 函数 python标准库实例大全

    今天学习第一模块的最后一课课程--函数: python的第一个函数: 1 def func1(): 2 print('第一个函数') 3 return 0 4 func1() 1 同时返回多种类型时, ...

  8. mongodb mapredReduce 多个条件分组(group by)

    from:https://my.oschina.net/chiyong/blog/289138 Mongodb 没有传统数据库的group函数,如果分组需要走MapReduce.这种MR与Hadoop ...

  9. 文件属性,获取,设置文件属性chown stat函数

    转载:http://c.biancheng.net/cpp/html/326.html man 2 stat查看手册 int stat(const char *path, struct stat *b ...

随机推荐

  1. bzoj 1602: [Usaco2008 Oct]牧场行走【瞎搞】

    本来想爆手速写个树剖,然而快下课了就手残写了了个n方的短小-- 暴力把查询的两个点中深的一个跳上来,加上边权,然后一起跳加边权就行了 #include<iostream> #include ...

  2. 11.3NOIP模拟赛

    /* 考虑贪心 把原序列排序后,对于原中位数往后所有比要更改到的值小的都改成它 正确性显然. */ #include<iostream> #include<cstdio> #i ...

  3. 浅谈KMP算法——Chemist

    很久以前就学过KMP,不过一直没有深入理解只是背代码,今天总结一下KMP算法来加深印象. 一.KMP算法介绍 KMP解决的问题:给你两个字符串A和B(|A|=n,|B|=m,n>m),询问一个字 ...

  4. [UOJ311]积劳成疾

    题解 dp 似乎这个最大值不好设计状态啊== 但是可以发现这\(n\)个点每个点都是相同的 可以设计状态\(f_{i,j}\)表示一个长度为\(i\)的一段区间的最大值不会超过\(j\)的价值 那么转 ...

  5. [USACO 2012 Jan Silver] Bale Share【DP】

    传送门:http://www.usaco.org/index.php?page=viewproblem2&cpid=107 没想到太不应该了,真的不应该啊! f[i][j][k]表示前i个包, ...

  6. 重写java.lang.String IndexOf()方法,实现对字符串以ASCII规则截取

    /** * 根据元数据和目标ascii位数截取字符串,失败返回-1 * @param sourceStr 元数据字符串 * @param endIndex 截取到第几位 * @return 结果字符串 ...

  7. ES6学习笔记(2)----变量的解构和赋值

    参考书<ECMAScript 6入门>http://es6.ruanyifeng.com/ 变量的解构和赋值 本质上:只要模式匹配,左边的变量就能被赋予右边对应的值 原则: 解构赋值的规则 ...

  8. Windows下使用JMeter

    简介 Apache JMeter是100%纯java桌面应用程序,被设计用来测试C/S结构的软件(例如web应用程序).它可以被用来测试包括基于静态和动态资源程序的性能,例如静态文件,Java Ser ...

  9. Struts1 MVC框架的工作原理

    MVC英文及Model-View-Controller,分别是模型(Model),视图(View)和控制(Controller).MVC模式的目的是实现web系统的职能分工. View:即用户交互界面 ...

  10. Node.js——render封装

    封装 挂在到res上