问题
在本实例中,你想创建一个结果集,其中包含小计(聚合分组的特定列)和总计(聚合整张表的特定列)。一个这样的结果集既包含 EMP 表中每种职位的薪水总额,也包含 EMP 表中所有薪水的总额,其中每种职位的薪水总额为小计,所有薪水的总额为总计。这种结果集如下所示。
JOB SAL
--------- ----------
ANALYST 6000
CLERK 4150
MANAGER 8275
PRESIDENT 5000
SALESMAN 5600
TOTAL 29025
解决方案
GROUP BY 子句的 ROLLUP 扩展完美地解决了这个问题。如果你使用的 RDBMS 不支持 ROLLUP,则可以使用标量子查询或 UNION 查询来解决这个问题,只是难度更大。
DB2 和 Oracle
使用聚合函数 SUM 计算薪水总额,并使用 GROUP BY 的 ROLLUP 扩展将结果组织为小计(针对不同职位)和总计(针对整张表)。
select case grouping(job)
when 0 then job
else 'TOTAL'
end job,
sum(sal) sal
from emp
group by rollup (job)
详细过程
首先,使用聚合函数 SUM 并按 JOB 分组,以计算不同职位的薪水总额。
select job, sum(sal) sal
from emp
group by job
JOB SAL
--------- -----
ANALYST 6000
CLERK 4150
MANAGER 8275
PRESIDENT 5000
SALESMAN 5600
然后,使用 GROUP BY 的 ROLLUP 扩展,以便在生成不同职位小计的同时生成总计。
select job, sum(sal) sal
from emp
group by rollup(job)
JOB SAL
--------- -------
ANALYST 6000
CLERK 4150
MANAGER 8275
PRESIDENT 5000
SALESMAN 5600
29025
最后,使用函数 GROUPING 在总计行的 JOB 列显示标签。如果 JOB 值为 NULL,那么函数 GROUPING 将返回 1,这表明 SAL 值为 ROLLUP 生成的总计。如果 JOB 值不为 NULL,则函数 GROUPING 将返回 0,这表明 SAL 值是 GROUP BY(而不是 ROLLUP)生成的。通过在 CASE 表达式中调用 GROUPING(JOB),可以根据情况返回职位名称或标签 TOTAL。
select case grouping(job)
when 0 then job
else 'TOTAL'
end job,
sum(sal) sal
from emp
group by rollup(job)
JOB SAL
--------- ----------
ANALYST 6000
CLERK 4150
MANAGER 8275
PRESIDENT 5000
SALESMAN 5600
TOTAL 29025
SQL Server 和 MySQL
首先,使用聚合函数 SUM 计算薪水总额,并使用 WITH ROLLUP 将结果组织为小计(针对不同职位)和总计(针对整张表)。然后,使用 COALESCE 给总计行提供标签 TOTAL。(如果不这样做,该行的 JOB 列将为 NULL。)
select coalesce(job,'TOTAL') job,
sum(sal) sal
from emp
group by job with rollup
在 SQL Server 中,也可以像 Oracle/DB2 解决方案那样使用函数 GROUPING(而不是函数 COALESCE)来确定聚合等级。
PostgreSQL
与 SQL Server 和 MySQL 解决方案类似,也可以使用 GROUP BY 的 ROLLUP 扩展,但语法稍有不同。
select coalesce(job,'TOTAL') job,
sum(sal) sal
from emp
group by rollup(job)
补充
GROUPING函数
可以接受一列,返回0或者1。如果列值为空,那么GROUPING()返回1;如果列值非空,那么返回0。GROUPING只能在使用ROLLUP或CUBE的查询中使用。
当需要在返回空值的地方显示某个值时,GROUPING()就非常有用。
ROLLUP函数
ROLLUP是GROUP BY子句的扩展。 ROLLUP选项允许包含表示小计的额外行,通常称为超级聚合行,以及总计行。 通过使用ROLLUP选项,可以使用单个查询生成多个分组集。
使用语法:group by rollup(a,b)
说明:针对 a 列、b 列分别进行分组,再针对 (a,b) 组合列进行分组,最后汇总。
rollup通常和group by语句一起使用,是根据维度在分组的结果集中进行聚合操作
点个赞吧,这对我十分重要!