SQL 识别非小计行,你已经知道如何使用 GROUP BY
子句的 CUBE
扩展语法生成报表,并且你需要知道如何区分哪些行是由普通的 GROUP BY
子句产生的,哪些行是由 CUBE
或 ROLLUP
产生的。
SQL 识别非小计行 问题描述
你已经知道如何使用 GROUP BY
子句的 CUBE
扩展语法生成报表,并且你需要知道如何区分哪些行是由普通的 GROUP BY
子句产生的,哪些行是由 CUBE
或 ROLLUP
产生的。
下面给出了一组利用 GROUP BY
的 CUBE
扩展语法生成的查询结果集,它是 EMP
表中员工工资的一个分类汇总结果。
DEPTNO JOB SAL
------ --------- -------
29025
CLERK 4150
ANALYST 6000
MANAGER 8275
SALESMAN 5600
PRESIDENT 5000
10 8750
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
20 10875
20 CLERK 1900
20 ANALYST 6000
20 MANAGER 2975
30 9400
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
以上报表展示了按照 DEPTNO
和 JOB
分组计算出来的(每个 DEPTNO
对应的每一种 JOB
的)工资合计值,按照 DEPTNO
分组计算出来的工资合计值,按照 JOB
分组计算出来的工资合计值,以及最后的总计(EMP
表的工资合计值)。你希望能清楚地识别上述各种聚合运算的维度,并标记出每一个聚合运算结果分别属于哪一类。(也就是说,给定的 SAL
值代表的是按照 DEPTNO
分组计算的结果,还是按照 JOB
分组计算的结果,或者是总计?)你希望返回如下所示的结果集。
DEPTNO JOB SAL DEPTNO_SUBTOTALS JOB_SUBTOTALS
------ --------- ------- ---------------- -------------
29025 1 1
CLERK 4150 1 0
ANALYST 6000 1 0
MANAGER 8275 1 0
SALESMAN 5600 1 0
PRESIDENT 5000 1 0
10 8750 0 1
10 CLERK 1300 0 0
10 MANAGER 2450 0 0
10 PRESIDENT 5000 0 0
20 10875 0 1
20 CLERK 1900 0 0
20 ANALYST 6000 0 0
20 MANAGER 2975 0 0
30 9400 0 1
30 CLERK 950 0 0
30 MANAGER 2850 0 0
30 SALESMAN 5600 0 0
SQL 识别非小计行 解决方案
使用 GROUPING
函数判断哪些值是 CUBE
或 ROLLUP
的小计结果,即超级聚合(supera ggregate)值。下面是 DB2 和 Oracle 的示例代码。
1 select deptno, job, sum(sal) sal,
2 grouping(deptno) deptno_subtotals,
3 grouping(job) job_subtotals
4 from emp
5 group by cube(deptno,job)
相较于 DB2 和 Oracle 解决方案,SQL Server 解决方案唯一的不同之处在于 CUBE/ROLLUP
子句的语法。
1 select deptno, job, sum(sal) sal,
2 grouping(deptno) deptno_subtotals,
3 grouping(job) job_subtotals
4 from emp
5 group by deptno,job with cube
本实例的重点在于展示如何使用 CUBE
和 GROUPING
处理小计计算。在写作本书时,PostgreSQL 和 MySQL 尚不支持 CUBE
或 GROUPING
。
SQL 识别非小计行 扩展知识
如果 DEPTNO_SUBTOTALS
等于 0,并且 JOB_SUBTOTALS
等于 1(此时 JOB
是 Null
),那么 SAL
值就是 CUBE
查询生成的、按照 DEPTNO
分组的小计结果。如果 JOB_SUBTOTALS
等于 0,并且 DEPTNO_SUBTOTALS
等于 1(此时 DEPTNO
是 Null
),那么 SAL
值就是 CUBE
查询生成的、按照 JOB
分组的小计结果。如果 JOB_SUBTOTALS
和 DEPTNO_SUBTOTALS
都等于 1,那么 SAL
值就是 CUBE
查询生成的工资总计。DEPTNO_SUBTOTALS
和 JOB_SUBTOTALS
都等于 0 的行则是通常的聚合运算结果(每个 DEPTNO/JOB
组合对应的 SAL
合计)。