SQL 多维度聚合运算,你想同时进行不同维度的聚合运算。例如,你希望得到一个结果集,其中包括每个员工的名字、部门、他所在部门的员工总数(包括他自己)、和他做相同工作的员工总数(该合计值中也包括他自己),以及 EMP 表中的员工总人数。
SQL 多维度聚合运算 问题描述
你想同时进行不同维度的聚合运算。例如,你希望得到一个结果集,其中包括每个员工的名字、部门、他所在部门的员工总数(包括他自己)、和他做相同工作的员工总数(该合计值中也包括他自己),以及 EMP 表中的员工总人数。最终的结果集如下所示。
SQL 多维度聚合运算 解决方案
有了窗口函数,很容易解决本问题。对于不支持窗口函数的数据库,我们可以使用标量子查询。
DB2、Oracle 和 SQL Server
使用窗口函数 COUNT OVER,按照不同的分区或分组执行聚合运算。
PostgreSQL 和 MySQL
在 SELECT 列表里使用标量子查询,基于不同的分组执行聚合运算。
SQL 多维度聚合运算 扩展知识
DB2、Oracle 和 SQL Server
这个实例充分展示了窗口函数的威力和方便性。只要简单地指定好不同的聚合运算维度,就能轻松创建出非常详尽的报表,不需要一次又一次的自连接操作,也不需要在 SELECT 列表中编写冗长笨重、性能低下的子查询。窗口函数 COUNT OVER 就这样独力完成了全部工作。为了更深入地理解输出结果,你先仔细观察每个 COUNT 操作的 OVER 子句。
请记住 OVER 子句的主要组成部分:首先是分区,由 PARTITION BY 指定;然后是帧(frame)或者窗口(window),由 ORDER BY 指定。我们来看第一个 COUNT,它的分区是 DEPTNO。EMP 表的数据将按照 DEPTNO 分组,并将针对每个组执行 COUNT 操作。由于没有指定帧或窗口子句(没有 ORDER BY),分组包含的全部行都会被纳入计数范围。PARTITION BY 子句会找出所有可能的 DEPTNO 值,然后调用 COUNT 函数统计每一种 DEPTNO 对应的行数。对于本例而言,COUNT(*)OVER(PARTITION BY DEPTNO) 中的 PARTITION BY 子句能够识别出的分区值会是 10、20 和 30。
第二个 COUNT 的处理过程也是如此,只不过这次要按照 JOB 分区。最后一个 COUNT 并没有指定任何分区,只放了一个空括号。空括号是指“整张表”。因此,虽然前两个 COUNT 基于指定的分组或分区进行聚合运算,最后一个 COUNT 则会计算出整个 EMP 表的行数。
请记住
WHERE子句执行过后窗口函数才会被评估执行。如果我们使用WHRE条件先行过滤掉了部分数据,例如删除了DEPTNO等于10的员工,那么TOTAL值将变成11,而不再是14。窗口函数执行过后若还想再做一些结果过滤,就必须把窗口函数查询放进内嵌视图,并从该视图中删除我们不希望看到的数据。
PostgreSQL 和 MySQL
对于主查询返回的每一行数据(EMP E 中的行),在 SELECT 列表里使用多个标量子查询基于每个 DEPTNO 和 JOB 生成不同的计数值。为得到 TOTAL 值,只要再写一个标量子查询获取 EMP 表的员工总人数即可。
极客教程