SQL 组合使用外连接查询与聚合函数,略微修改了 EMP_BONUS
表的数据,使得部门编号为 10 的员工中只有部分人获得了奖金。考虑如下所示的 EMP_BONUS
表和查询语句,该查询(表面上)计算出了部门编号为 10 的员工的工资总额和奖金总额。
SQL 组合使用外连接查询与聚合函数 问题描述
略微修改了 EMP_BONUS
表的数据,使得部门编号为 10 的员工中只有部分人获得了奖金。考虑如下所示的 EMP_BONUS
表和查询语句,该查询(表面上)计算出了部门编号为 10 的员工的工资总额和奖金总额。
奖金总额的结果是正确的,但工资总额却不是部门编号为 10
的员工的工资总额。下面的查询语句解释了为什么工资总额不正确。
上述查询没有计算部门编号为 10
的全部员工的工资总额,实际上只有 MILLER 的工资被计入总和,而且被错误地计算了两次。其实,你最终想得到如下所示的结果集。
SQL 组合使用外连接查询与聚合函数 解决方案
下面的解决方案也和 3.9 节的类似,不同之处在于要外连接 EMP_BONUS
表,确保把部门编号为 10
的全部员工都包括进来。
DB2、MySQL、PostgreSQL 和 SQL Server
外连接 EMP_BONUS
表,然后去掉部门编号为 10
的员工的重复项,再计算工资总和。
也可以使用窗口函数 SUM OVER
。
Oracle
对于 Oracle 9i 数据库及其后续版本,上述解决方案仍然适用。除此之外,我们也可以使用 Oracle 专有的外连接语法。对于 Oracle 8i 数据库及更早的版本,只能使用该语法实现外连接。
与 DB2 及其他数据库类似,Oracle 8i 数据库也支持 SUM OVER
语法,但必须把上面的查询语句里出现的外连接改为 Oracle 专有的语法。
SQL 组合使用外连接查询与聚合函数 扩展知识
本实例“问题”部分中的第二个查询语句连接了 EMP
表和 EMP_BONUS
表,却只返回了员工 MILLER 的两行数据,这是导致 EMP
表的工资总额计算出错的原因(部门编号为 10
的其他员工没有奖金,他们的工资没有被计入总和)。解决办法则是把 EMP
表外连接到 EMP_BONUS
表,这样一来,那些没有奖金的员工也会被计算进来。如果一个员工没有奖金,那么 EMP_BONUS
表中的 TYPE
就是 Null
值。注意到这一点非常重要,因为 CASE
语句部分已经在 3.9 节的基础上稍微有了变动。如果 EMP_BONUS
表中的 TYPE
为 Null
值,则 CASE
表达式会返回 0,这样就不会对总和产生影响。
下面的查询语句是另一种解决方案。首先计算部门编号为 10
的员工的工资总额,然后再连接 EMP
表和 EMP_BONUS
表(这样就避免了使用外连接)。下面的查询语句适用于所有的关系数据库管理系统。