Oracle Group by增强功能(Rollup,Cube,Grouping sets及Grouping函数)

Rollup,Cube,Grouping sets都是用于在Group by的基础上进行小组小计,合计等增强操作,多用于如公司-部门-小组等多级运算。

在本次测试中用到数据表如下(建表语句及测试数据在文章末尾):
包含员工ID,员工姓名,部门ID,职位ID,薪资
这里写图片描述

1.Rollup

1.1 使用实例
SELECT department_id, job_id,employee_id,SUM(salary)
FROM employees
WHERE department_id < 60
GROUP BY ROLLUP(department_id, job_id,employee_id);

该语句作用为显示各员工薪水,各职位薪水总和,及各部门薪水总和,及公司全部薪水总和(因数据过多仅取部门号<60的部门代表全公司)。
结果如下:
这里写图片描述

1.2 执行原理

其执行方式是根据ROLLUP后的参数字段,从右向左依次减少一个进行分组计算,并将每次分组的结果进行union操作。如参数字段个数为n,则进行n+1层分组计算。

1.3 实例解释

如例子中结构为:公司总薪水-部门总薪水-职位总薪水-员工总薪水(4层)

正如显示结果中9行为50号部门中所有职位是ST_MAN的员工的薪水,11-14行为50号部门中所有职位是ST_CLERK的员工的薪水(1层),10行为50号部门中ST_MAN职位的总薪水,15行为50号部门中ST_CLERK职位的总薪水(2层),16行为50号部门的总薪水(3层),17行为公司的总薪水(4层),即按照公司总薪水-部门总薪水-职位总薪水-员工总薪水从右向左依次减少一个参数后,分组计算。

可以按照排列组合的方式来记为
A B C
A B
A
_

2.Cube

2.1 使用实例
SELECT department_id, job_id,SUM(salary)
FROM employees
WHERE department_id < 60
GROUP BY cube(department_id, job_id)
order by department_id;

该语句作用为显示各部门各职位薪水总和,及各部门薪水总和,全公司各职位薪水,无各员工薪水,及公司全部薪水总和(因数据过多仅取部门号<60的部门代表全公司,加粗地方为与Rollup不同的地方)。
结果如下:
这里写图片描述

2.2 执行原理

其执行方式是根据Cube后的参数字段,如参数字段个数为n,则进行n的平方次层分组计算,并将结果union。

2.3 实例解释

如例子中结构为:公司总薪水-部门总薪水-职位总薪水

正如显示结果中6行为50号部门中ST_CLERK职位的总薪水,7行为50号部门中ST_MAN职位的总薪水(1层),8行为50号部门的总薪水(2层),9-13行为公司中各个职位的总薪水(3层),14行为公司总薪水(4层),即进行了2^2=4层的分组计算。

扫描二维码关注公众号,回复: 2200020 查看本文章

可以按照排列组合的方式来记为
A B
A
B
_

3.Grouping sets

3.1 使用实例
SELECT department_id, job_id,manager_id,avg(salary)
FROM employees
where department_id < 60
GROUP BY GROUPING SETS
((department_id,job_id), (job_id,manager_id))
order by department_id;

该语句作用为计算部门中各个职位的平均工资,与各个职位中各个经理的平均工资,及两组计算。
执行结果:
这里写图片描述

3.2 执行原理

Grouping sets的作用原理是括号中的每个()为一组,对所有的组进行union操作。

如途中所示1-5行为部门中各个职位的平均工资,5-10行为各个职位中各个经理的平均工资。

4.Grouping函数

在使用Rollup、Cube操作中会出现列为null的情况,而如果表中数据也存在null的情况时,容易出现无法判断是由Rollup/Cube产生的null还是本身数据的null,此时就需要用Grouping函数来解决。

4.1 使用实例
SELECT department_id DEPTID, job_id JOB,SUM(salary),
GROUPING(department_id) GRP_DEPT,
GROUPING(job_id) GRP_JOB
FROM employees
WHERE department_id < 50
GROUP BY ROLLUP(department_id, job_id);

使用rollup计算各部门各职位的总薪水,各部门的总薪水及公司的总薪水,使用Grouping标注department_id和job_id(避免数据过多混乱仅取部门号<50的部门)。

执行结果:
这里写图片描述

4.2 实例解释

如结果图可看出第2行、第4行的JOB_ID列为rollup产生null时,由Grouping函数标注的GRP_JOB列为1,第6行中由GRP_DEPT与GRP_JOB均为1,即当Rollup产生null时,使用Grouping标注的列即为1。

如需了解更多的Grouping操作可以去这位作者这里阅读,这里更加正规全面:
https://blog.csdn.net/cdhql/article/details/7074579

建表语句及测试数据:

(EMPLOYEE_ID NUMBER(6) NOT NULL,
FIRST_NAME VARCHAR2(20),
LAST_NAME VARCHAR2(25) NOT NULL,
EMAIL VARCHAR2(25) NOT NULL,
PHONE_NUMBER VARCHAR(20),
HIRE_DATE DATE NOT NULL,
JOB_ID VARCHAR2(10) NOT NULL,
SALARY NUMBER(8,2),
COMMISSION_PCT NUMBER(2,2),
MANAGER_ID NUMBER(6),
DEPARTMENT_ID NUMBER(4));

insert into employees values(100,'Steven','King','SKING','515.123.4567',to_date('1987-06-17','YYYY-MM-DD'),'AD_PRES',24000,NULL,NULL,90);
insert into employees values(101,'Neena','Kochhar','NKOCHHAR','515.123.4568',to_date('1989-09-21','YYYY-MM-DD'),'AD_VP',17000,NULL,100,90);
insert into employees values(102,'Lex','De Haan','LDEHAAN','515.123.4569',to_date('1993-01-13','YYYY-MM-DD'),'AD_VP',17000,NULL,100,90);
insert into employees values(103,'Alexander','Hunold','AHUNOLD','590.423.4567',to_date('1990-01-03','YYYY-MM-DD'),'IT_PROG',9000,NULL,102,60);
insert into employees values(104,'Bruce','Ernst','BERNST','590.423.4568',to_date('1991-05-21','YYYY-MM-DD'),'IT_PROG',6000,NULL,103,60);
insert into employees values(107,'Diana','Lorentz','DLORENTZ','590.423.5567',to_date('1999-02-07','YYYY-MM-DD'),'IT_PROG',4200,NULL,103,60);
insert into employees values(124,'Kevin','Mourgos','KMOURGOS','650.123.5234',to_date('1999-11-16','YYYY-MM-DD'),'ST_MAN',5800,NULL,100,50);
insert into employees values(141,'Trenna','Rajs','TRAJS','650.121.8009',to_date('1995-10-17','YYYY-MM-DD'),'ST_CLERK',3500,NULL,124,50);
insert into employees values(142,'Curtis','Davies','CDAVIES','650.121.2994',to_date('1997-01-29','YYYY-MM-DD'),'ST_CLERK',3100,NULL,124,50);
insert into employees values(143,'Randall','Matos','RMATOS','650.121.2874',to_date('1998-05-15','YYYY-MM-DD'),'ST_CLERK',2600,NULL,124,50);
insert into employees values(144,'Peter','Vargas','PVARGAS','650.121.2004',to_date('1998-07-09','YYYY-MM-DD'),'ST_CLERK',2500,NULL,124,50);
insert into employees values(149,'Eleni','Zlotkey','EZLOTKEY','011.44.1344.429018',to_date('2000-06-29','YYYY-MM-DD'),'SA_MAN',10500,.2,100,80);
insert into employees values(174,'Ellen','Abel','EABEL','011.44.1644.429267',to_date('1996-05-11','YYYY-MM-DD'),'SA_REP',11000,.3,149,80);
insert into employees values(176,'Jonathon','Taylor','JTAYLOR','011.44.1644.429265',to_date('1998-05-24','YYYY-MM-DD'),'SA_REP',8600,.2,149,80);
insert into employees values(178,'Kimberely','Grant','KGRANT','011.44.1644.429263',to_date('1999-05-24','YYYY-MM-DD'),'SA_REP',7000,.15,149,NULL);
insert into employees values(200,'Jennifer','Whalen','JWHALEN','515.123.4444',to_date('1987-09-17','YYYY-MM-DD'),'AD_ASST',4400,NULL,101,10);
insert into employees values(201,'Michael','Hartstein','MHARTSTE','515.123.5555',to_date('1996-02-17','YYYY-MM-DD'),'MK_MAN',13000,NULL,100,20);
insert into employees values(202,'Pat','Fay','PFAY','603.123.6666',to_date('1997-08-17','YYYY-MM-DD'),'MK_REP',6000,NULL,201,20);
insert into employees values(205,'Shelley','Higgins','SHIGGINS','515.123.8080',to_date('1994-06-07','YYYY-MM-DD'),'AC_MGR',12000,NULL,101,110);
insert into employees values(206,'William','Gietz','WGIETZ','515.123.8181',to_date('1994-06-07','YYYY-MM-DD'),'AC_ACCOUNT',8300,NULL,205,110);

以上为本人学习Oracle递归操作后的个人理解与总结,如有错误还望指正修改,欢迎交流~

转载留个言哈~

猜你喜欢

转载自blog.csdn.net/CircleLY/article/details/81088213