3.09 聚集和联接
Posted 长城之上是千亿的星空,星空之上是不灭的守望。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3.09 聚集和联接相关的知识,希望对你有一定的参考价值。
问题:要在包含多个表的查询中执行聚集运算,要确保表间连接不能使聚集运算发生错误.例如,要查找在部门10中所有员工的工资合计和奖金合计.由于有些员工的奖金激励不只一条,在表emp和表emp_bonus之间做连接会导致聚集函数sum算得的值错误.
现在,考虑一下下面的返回的在部门10中所有员工的工资和奖金的查询。表bonus中的type字段决定奖金额,类型1的奖金为员工工资的10%,类型2为20%,类型3为30%。
select e.empno,
e.ename,
e.sal,
e.deptno,
e.sal*case when eb.type = 1 then .1
when eb.type = 2 then .2
else .3
end as bonus
from emp e ,emp_bonus eb
where e.empno = eb.empno
and e.deptno = 10
进行到这,一切正常,然而为了计算奖金总数而跟表emp_bonus做联接时,错误出现了:
select deptno,
sum(sal) as total_sal,
sum(bonus) as total_bonus
from (
select e.empno,e.ename,e.sal,e.deptno,
e.sal*case when eb.type = 1 then .1
when eb.type = 2 then .2
else .3
end as bonus
from emp e,emp_bonus eb
where e.empno = eb.empno
and e.deptno = 10
)x
group by deptno
尽管total_bonus所返回的值是正确的,total_sal却是错误的。
total _sal为什么错了,因为联接导致sal列存在重复。考虑下面的查询。该查询联接表emp和emp_bonus
select e.ename,e.sal
from emp e,emp_bonus eb
where e.empno = eb.empno
and e.deptno =10
现在可以很容易的看出total_sal为什么错了,因为miller的工资被统计了两次。
解决方案:当处理聚集与联接混合操作时,一定要小心。如果联接产生重复行,可以有两种方法来避免聚集函数计算错误,方法之一,只要在调用聚集函数时使用关键字distinct,这样每个值只参与计算一次,另一种方法是,在进行连接前先只想聚集操作(在内联视图中),这样,因为聚集计算已经在连接前完成了,所以就可以避免聚集函数计算错误,从而可以完全避免产生此问题。下面列出的解决方案使用了distinct关键字,而”讨论”部分将讨论如何在联结前使用内联视图来只想聚集操作。
select deptno,
sum(distinct sal) as total_sal,
sum(bonus) as total_bonus
from (
select e.empno,
e.ename,
e.sal,
e.deptno,
e.sal *case when eb.type = 1.then .1
when eb.type = 2 then .2
else .3
end as bonus
from emp e ,emp_bonus eb
where e.empno = eb.empno
and e.deptno = 10
)x
group by deptno
以上是关于3.09 聚集和联接的主要内容,如果未能解决你的问题,请参考以下文章