查看: 46699|回复: 15

[精华] Oracle group by 用法实例详解

[复制链接]
论坛徽章:
2
ITPUB十周年纪念徽章
日期:2011-11-01 16:26:292012新春纪念徽章
日期:2012-01-04 11:57:56
跳转到指定楼层
1#
发表于 2011-5-24 21:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Group by的语法
Select [filed1,fild2,]聚合函数(filed),
[Grouping(filed),]
[Grouping_id(filed1,filed2,…)]
From tablename
Where condition
[Group by {rollup|cube}(filed,filed2)]
[having condition]
[order by filed1]
一、基本用法:

(1)我们通过几个例子来研究groupby的基本用法
创建测试表
SQL> create table sales(
2 empid number, --雇员ID
3 depid number, - -部门ID
4 area varchar(20), --区域
5 salenum number); --销售额

表已创建。

SQL> insert into sales values(1,1,'china',10);
SQL> insert into sales values(2,1,'china',10);
SQL> insert into sales values(3,1,'china',10);
SQL> insert into sales values(3,1,'china',10);
SQL> insert into sales values(3,1,'china',10);
SQL> insert into sales values(1,1,'china',10);
SQL> insert into sales values(2,1,'china',10);
SQL> insert into sales values(4,2,'china',10);
SQL> insert into sales values(4,2,'china',10);
SQL> insert into sales values(5,3,'us',10);
SQL> insert into sales values(5,3,'us',10);
需求1,按部门统计销售额 (简单用法)
SQL> select depid,sum(salenum) from sales group by depid;
DEPID SUM(SALENUM)
---------- ------------
1        70
2        20
3        20
需求2,按部门统计销售额,并且只显示销售总额小于30的部门及销售额(使用having子句)
SQL> select depid,sum(salenum) totalnum from sales
group by depid
having sum(salenum) <30;
DEPID SUM(SALENUM)
---------- ------------
2        20
3        20
注解:需求2需要使用having字名,而且在子句中不能使用别名,必须使用在select语句中书写的形式
(2)Where 和having的区别
Wheret和having子句都用来筛选数据,但是where是针对原数据进行筛选,而having子句只是针对汇总后的结果进行筛选,所以在需求二的例子中,想要对销售总额进行过滤只能使用having子句
(3)使用order by 排序
SQL> select depid,sum(salenum) from sales group by depid;
DEPID SUM(SALENUM)
---------- ------------
1       70
2       20
3       20
注意观察需求1的例子,depid是已经按照在depid升序排列的,这是因为oracle在做聚合统计的时候会首先对字段进行排序,所以最终的结果是按照升序进行排列的,如果order by后跟着多个字段,默认排序是先对第一个字段升序排序,然后再排第二个字段,以此类推,所以如果在应用中仅仅需要长序排序可以不用加order by 参数,毕竟这会影响性能
二、扩展用法:

扩展用法使用下面的表进行实验研究
SQL> create table testgroup(
2 a varchar(5),
3 b varchar(5),
4 c varchar(5),
5 n number);
建完测试表,然后插入两条测试数据
SQL> insert into testgroup values('a1','b1','c1',10);
SQL> insert into testgroup values('a1','b1','c1',20);
我们使用基本的group by 可以得到以下结果
SQL> select a,b,c,sum(n) total from testgroup group by a,b,c;
A        B      C     TOTAL
----- ----- ----- ----------
a1      b1     c1     30
(1)使用rollup操作符

Rollup意思有”卷起,汇总”的意思,他可以在使得在其括号中的字段,按从右到左的顺序分别group后显示,类似我们用多个group by 语句,然后union all起来,我们把针对上面的测试表,使用rollup操作符,看看效果
SQL> select a,b,c,sum(n) total from testgroup group by rollup(a,b,c);
Result:
ABCTOTAL
a1b1c130
a1b1 30
a1 30
30
从上面结果可以看出, 除了对(a1,b1,c1)进行了汇总外,又从右向左分别对子句中的”a,b,c”字段进行了汇总,例如(a1,b1),(a1) ()
(2)使用cube操作符

Cube意思是立方,使用该操作符可以对操作符内的字段,进行遍历组合汇总,例如cube(a,b,c),那么就会产生8种组合结果,分别如下”a-b-c”,”a-b”,”a”,”a-c”,” b-c”,”b”,”c”,”空”,看下面的例子
SQL> select a,b,c,sum(n) total from testgroup group by cube(a,b,c);
        Result:
ABCTOTAL
30
c130
b1 30
b1c130
a1 30
a1 c130
a1b1 30
a1b1c130
(3),使用grouping(filed)函数

使用grouping 函数必须先理解rollup 和cube操作符,那么grouping函数有什么用呢?在日常应用中,我们通过rollup或者cube对汇总进行了汇总,汇总后的结果往往要传送到应用程序端,在应用程序端我们必须要有一个依据来判断某行数据是不是按照rollup或cube进行汇总,grouping函数可以用来产生这个依据,他可以接收一个参数,判断该参数是否为null,是则返回1,否则返回0,我样可以据此来判断该是否按某列进行汇总统计的,当然在实验应用中,0和1看起来不那么直观,我们可以使用decode或者case函数进行转议,让查看结果看起来更直观,请看以下例子
SQL> select grouping(a) ca,grouping(b) cb,grouping(c) cc, a,b,c,sum(n) from testgroup group by rollup(a,b,c);
Result:
CACBCCABCSUM(N)
000a1b1c130
001a1b1 30
011a1 30
111 30
(4)使用grouping_id(filed1,file2,…)函数

使用grouping函数有时候感觉不是那么灵活的,他只能接收一个字段,而grouping_id()函数则可以接收多个字段,GROUPING_ID()函数可以接受一列或多列,返回按GROUPING位向量进行计算的十进制值。下面我们通过一个例子来研究grouping_id函数是如何按照grouping函数的位向量进行计算的。
SQL> select grouping(a) ca,grouping(b) cb,grouping_id(a,b) caandb, a,b,sum(n) from testgroup group by rollup(a,b);
Result:
CACBCAANDBABSUM(N)
000a1b130
011a1 30
113 30

位向量计算方法:如上例,
第一行,CA=0,CB=0,那么位向量就是“00”,换算成十进制是0
第二行,CA=0,CB=1,那么位向量就是‘01’,换算成十进制是1
第三行,CA=1,CB=1,那么位向量就是‘11’,换算成十进制是3
请注意上例中grouping_id的计算值跟括号内的字段顺序有关,上例中书写顺序是grouping_id(a,b),a字段在前面,如果换下顺序grouping_id(b,a),计算结果是不一样的,看下例
SQL> select grouping(a) ca,grouping(b) cb,grouping_id(b,a) caandb, a,b,sum(n) from testgroup group by rollup(a,b);
Result:
CACBCAANDBABSUM(N)
000a1b130
012a1 30
113 30

看看第二行红色字体,grouping_id中的字段顺序发生了变化,位向量值也不一样了
(4-1) grouping_id()函数的用途
上面讲了grouping_id的用法,但在日常工作中,我们如何应用该函数呢?其实只要了解了他的原理及用法,要怎么用,就看我们是否可以灵活使用了,下面介绍一种常见的用法:
假如我们要对某testgroup进行分组统计,并且过滤掉不包括小计或总计的行,这时grouping_id就有用武之地了,我们可以利用grouping_id的值结合having子句,通过判断grouping_id是否大于0来过滤掉不需要的行。
SQL> select grouping(a) ca,grouping(b) cb,grouping_id(a,b) caandb, a,b,sum(n) from testgroup group by rollup(a,b) having grouping_id(a,b)>0;
Result:
CACBCAANDBABSUM(N)
011a1 30
113 30

论坛徽章:
2
ITPUB 11周年纪念徽章
日期:2012-10-09 18:11:482013年新春福章
日期:2013-02-25 14:51:24
2#
发表于 2011-5-30 16:07 | 只看该作者
up!

使用道具 举报

回复
论坛徽章:
0
3#
发表于 2011-5-30 17:36 | 只看该作者
很少见,,顶顶

使用道具 举报

回复
论坛徽章:
1088
金色在线徽章
日期:2007-04-25 04:02:08金色在线徽章
日期:2007-06-29 04:02:43金色在线徽章
日期:2007-03-11 04:02:02在线时间
日期:2007-04-11 04:01:02在线时间
日期:2007-04-12 04:01:02在线时间
日期:2007-03-07 04:01:022008版在线时间
日期:2010-05-01 00:01:152008版在线时间
日期:2011-05-01 00:01:342008版在线时间
日期:2008-06-03 11:59:43ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30
4#
发表于 2011-5-30 19:42 | 只看该作者
原创不错,深度不足,支持

使用道具 举报

回复
论坛徽章:
58
生肖徽章2007版:马
日期:2009-11-06 23:12:33授权会员
日期:2013-01-10 14:38:592013年新春福章
日期:2013-02-25 14:51:24马自达
日期:2013-08-07 10:54:45红旗
日期:2013-08-09 13:48:48劳斯莱斯
日期:2013-09-12 15:56:37萤石
日期:2013-10-31 08:44:19优秀写手
日期:2013-12-18 09:29:13Jeep
日期:2014-01-14 10:53:432014年新春福章
日期:2014-02-18 16:43:09
5#
发表于 2011-5-30 23:58 | 只看该作者
支持一下

使用道具 举报

回复
论坛徽章:
519
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
6#
发表于 2011-5-31 22:47 | 只看该作者

使用道具 举报

回复
论坛徽章:
2
数据库板块每日发贴之星
日期:2011-07-24 01:01:01
7#
发表于 2011-6-1 16:56 | 只看该作者
赞一个

使用道具 举报

回复
论坛徽章:
69
生肖徽章2007版:羊
日期:2008-11-14 14:42:19复活蛋
日期:2011-08-06 08:59:05ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20版主4段
日期:2012-05-15 15:24:11
8#
发表于 2011-6-2 10:04 | 只看该作者
似乎都没有举例会用在什么样的需求中...

使用道具 举报

回复
论坛徽章:
43
生肖徽章2007版:羊
日期:2008-05-27 15:39:39铁扇公主
日期:2012-01-25 17:44:56茶鸡蛋
日期:2012-06-10 20:12:42奥运会纪念徽章:跳水
日期:2012-07-09 16:38:12奥运会纪念徽章:手球
日期:2012-07-24 08:28:36奥运会纪念徽章:艺术体操
日期:2012-09-19 13:18:16奥运会纪念徽章:柔道
日期:2012-09-26 12:34:19ITPUB 11周年纪念徽章
日期:2012-10-09 18:09:19蜘蛛蛋
日期:2012-11-06 19:43:442013年新春福章
日期:2013-02-25 14:51:24
9#
发表于 2011-6-2 11:43 | 只看该作者

回复 #2 wed0402 的帖子

好強哦,很少有用到過,學習!

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
10#
发表于 2011-6-5 12:26 | 只看该作者
原帖由 newkid 于 11-5-31 22:47 发表
这也有一个:
http://www.itpub.net/thread-998611-1-1.html


这个要更好一些

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表