我们要统计 emp 表中每个部门的工资及公司的总工资,该怎么写 SQL 呢?
emp 表的数据
有一个完美的解决方案是使用 GROUP BY
子句的 ROLLUP
扩展。ROLLUP
在分组统计的基础上,再对结果进行相同操作(SUM
、AVG
、COUNT
)的聚合。
在 MySQL
中,解决这个问题的 SQL 可以这么写:
SELECT IFNULL(deptno, 'TOTAL') AS deptno, SUM(sal) sal FROM emp GROUP BY deptno WITH ROLLUP ;
注意:
ORDER BY
不能在ROLLUP
中使用,两者为互斥关键字;- 如果分组的列包含
NULL
值,那么ROLLUP
的结果可能不正确,因为使用ROLLUP
进行分组统计时,NULL
具有特殊意义。因此在进行ROLLUP
操作前先将分组列中的NULL
值转换成一个不可能存在的值,或者没有特别含义的值。
对于不支持 ROLLUP
语法的数据库,可以使用 UNION/UNION ALL
实现相同的效果。
使用 UNION/UNION ALL
的解决方案:
SELECT deptno,SUM(sal) sal FROM emp GROUP BY deptno UNION ALL SELECT 'TOTAL' AS deptno,SUM(sal) AS sal FROM emp
如果我们想按照 deptno、job 以及 deptno/job 组合分别计算出工资合计值,又该怎么做呢?
要实现的效果如下图:
在 MySQL 上实现的思路:
- 按照各个组合条件分别计算出结果;
- 使用
UNION ALL
把 1 中统计出来的结果合并到一块。
SELECT deptno AS '部门编号',job '职位', '按部门和职位合计' AS '计算规则', SUM(sal) '工资合计' FROM emp GROUP BY deptno,jobUNION ALLSELECT deptno,NULL,'按部门合计',SUM(sal)FROM emp GROUP BY deptnoUNION ALLSELECT NULL,job,'按职位合计',SUM(sal)FROM emp GROUP BY jobUNION ALLSELECT NULL,NULL,'公司总计',SUM(sal)FROM emp