使用grouping进行分组查询,方便得到多种分组结果

在实际开发过程中,对数据进行的查询,常常是不仅要查询数据本身,还要对其进行分组查询。这时候最简单的方法是进行多次查询后将数据合并。但使用grouping可以更方便简洁地进行上述查询。
假设有如下数据表:

create table student(
id varchar2(32) primary key,
class varchar2(32),
name varchar2(32),
sex varchar2(32),
score integer);
insert into student values('20110101','1','张三','男',90);
insert into student values('20110102','1','李四','男',95);
insert into student values('20110103','1','小明','男',95);
insert into student values('20110104','1','李娜','女',93);
insert into student values('20110105','1','小茜','女',93);
insert into student values('20110201','2','张龙','男',90);
insert into student values('20110202','2','赵虎','男',95);
insert into student values('20110203','2','小倩','女',95);
insert into student values('20110204','2','珊珊','女',94);
insert into student values('20110205','2','小沐','女',94);
commit;

查询所有学生的成绩及按班级、性别分组后的平均成绩:
 
select id,
class,
decode(grouping_id(class, sex, name),
7,
'总平均',
3,
class || '班平均',
1,
class || '班' || sex || '生平均',
name) sname,
sex,
avg(score)
from student t
group by grouping sets((),(class),(class, sex),(class, sex, name, id))
order by grouping_id(class, sex, name), class, id

得到如下结果:
[img]http://dl.iteye.com/upload/attachment/0067/7103/acfea5a9-1606-3eb7-a7bb-76a719643a7f.jpg[/img]


可以看到,只要通过一次查询就得到了数据本身和各种分组数据。下面说明用到的特殊语句和函数:
1.group by grouping sets((),(class),(class, sex),(class, sex, name, id))
grouping sets 相当与将多个group by的分组条件合并,空的分组条件则是所有数据的总合计。上述语句就相当于查询时没有group条件、使用group by(class)、group by(class,sex)、
group by(class, sex, name, id)这四种情况下查询得到的数据合并到一起。

2.grouping_id(class, sex, name)
grouping_id(arg)函数判断其参数是否参与了分组,如果没有参与则返回1,如果参与了分组则返回0,如在本例中grouping_id(class)在除了总合计以外的结果集中class都参与了分组,即grouping_id(class)在第1~16行返回0,第17行返回1。而其多个参数的形式则将其每个参数进行grouping_id(arg)运算后返回的值拼成二进制后转换为十进制返回,即grouping_id(argn,...,arg2,arg1)=grouping_id(argn)*2^(n-1)+...+grouping_id(arg2)*2^1+grouping_id(arg1)*2^0('^'表示幂运算)。
在上述示例中,在1~10行结果相当于group by(class, sex, name, id)返回的结果,此时grouping_id(class, sex, name)的所有参数参与了分组,则返回值为(000)二进制=(0)十进制;第11~14行相当于group by(class,sex)的结果,此时class和sex参与了分组,grouping_id(class, sex, name)返回值为(001)二进制=(1)十进制;第15、16行相当于group by(class),此时class参与了分组,grouping_id(class, sex, name)返回值为(011)二进制=(3)十进制;而第17行相当于没有group条件,此时没有分组参数,则grouping_id(class, sex, name)返回值为(111)二进制=(7)十进制。

3.decode(grouping_id(class, sex, name),7, '总平均',3,class || '班平均',1,class || '班' || sex || '生平均',name)
decode(condition,arg1,return1,arg2,return2,...,argn,returnn,default)相当于如下语句:
 
if(condition = arg1) {
return return1;
}else if(condition = arg2) {
return return2;
}
......
else if(condition = argn) {
return returnn;
}else {
return defualt;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
“中级/进阶篇”讲解特点与内容:         本“中级”与“进阶”篇, 是面向初中级游戏研发人员,以及Unity中高级学习者。为了更加深入的刨析各个语法的本质,我们采用反编译解读IL中间语言的方式,来解构语法重点与难点。 中级篇内容主要讲解: .Net 框架、里氏替换原则(LSP)、类的属性极其本质特性、IS ,AS 关键字、字符串的“驻留性” 原理、深入解析Equals() 原理、枚举类型、自定义集合、深入解析动态集合特性与内部原理、泛型集合、泛型约束、初级委托与事件讲解等。 进阶篇是在中级篇的基础之上,进一步研究与讲解关于IO操作、序列化、正则表达式、系统委托(Action、Function、Predicate等)、反射原理与特性、Linq查询表达式、多线程、线程池、任务、Socket套接字编程(Tcp与UDP协议),以及最后使用Unity开发具备实战价值的通讯聊天程序等。C#“进阶篇”教学详细说明如下:1: IO操作与序列化      学习文件、目录、二进制文件、文本文件的读取与写入底层原理。学习文件序列化与反序列化技能。2: 正则表达式      学习正则表达式的强大作用与常用原字符的含义与应用场景。3: 深入委托与事件      学习Action、Func、Predicate 系统内置委托类型,已经适用场合。学习匿名方法、Lambda表达式。深入解析委托与事件的区别。4: 反射与特性      学习反射的概念与动态调用的重要应用价值,以及Type、Assembley核心类等,最后讲解“特性”技术。5: Linq 查询表达式     学习Linq 查询表达式对于“对象集合”(支持IEnumberable 或IEnumberable) 以及SQL数据库、XML文档方面的强大查询功能。    6: 多线程     学习多线程以及线程传参、线程取得返回数值技术,前台与后台线程、线程的同步、线程池、任务等技术。   7: Socket套接字通讯     学习Socket套接字通讯中,Tcp与UPD通讯协议的不同应用场景,以及各自的演示示例,最后用Unity开发一款实用性的聊天通讯工具。温习提示:           本C# for Unity 使用Virtual Studio2012,以及Unity5.2 进行开发与讲解。(学员使用更高版本,对学习没有任何影响)。      A:《C# For Unity系列之入门篇》https://edu.csdn.net/course/detail/4560B:《C# For Unity系列之基础篇》https://edu.csdn.net/course/detail/4595C: 《C# For Unity系列之中级篇》https://edu.csdn.net/course/detail/24422
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值