请看图:
这种状况咱们通常会使用左链接的方式。sql
select e.ENAME,d.LOC,eb.RECEIVED from emp e join dept d on(e.DEPTNO=d.DEPTNO) left join emp_bonus eb on(eb.EMPNO=e.EMPNO) order by 2
上面这种能够实现的,可是不利于咱们在写code语句中的复用。函数
下面是一种标量子查询个人方式,能够帮助咱们复用部分sql。优化
select e.ENAME,d.LOC,(select eb.RECEIVED from emp_bonus eb where e.EMPNO=eb.EMPNO) as RECEIVED from emp e join dept d on(e.DEPTNO=d.DEPTNO) order by 2
这里原理很简单,其实就是先设置了RECEIVED 行而后去查询。
一样这里有限制就是RECEIVED 查询出来必须只有一个结果,由于开辟了一个空间。code
在将来第600章中会介绍若是针对查询出多行的问题。blog
select e.DEPTNO,e.EMPNO,e.ENAME,e.SAL,e.SAL*case when eb.TYPE=1 then 0.1 when eb.TYPE=2 then 0.2 when eb.TYPE=3 then 0.3 end as bonus from EMP e,emp_bonus eb where e.EMPNO=eb.EMPNO and e.DEPTNO=10
如今只须要看到上图的表。it
如今有一个须要,就是要统计上面部门为10的SAL 和 bonus。io
这个时候通常想到的是聚合函数。class
select x.DEPTNO,sum(x.SAL) as total_sum,sum(x.bonus) as total_bonus from (select e.DEPTNO,e.EMPNO,e.ENAME,e.SAL,e.SAL*case when eb.TYPE=1 then 0.1 when eb.TYPE=2 then 0.2 when eb.TYPE=3 then 0.3 end as bonus from EMP e,emp_bonus eb where e.EMPNO=eb.EMPNO and e.DEPTNO=10) x group by x.DEPTNO
获得的结果为错误的。由于有人获得两次奖励:原理
那么可能会这样写:select
(select e.DEPTNO,e.EMPNO,e.ENAME,e.SAL,e.SAL*case when eb.TYPE=1 then 0.1 when eb.TYPE=2 then 0.2 when eb.TYPE=3 then 0.3 end as bonus from EMP e,emp_bonus eb where e.EMPNO=eb.EMPNO and e.DEPTNO=10) x group by x.DEPTNO
排除掉sal中相同的项增长,可是万一有人sal相同怎么办?这确定是一个问题。还有一个问题就是若是这个部门有一部分人若是没有获得bonus怎么办?也就是说有一部分SAL没显示出来
select x.DEPTNO, d.total_sum,sum(x.bonus) as total_bonus from (select e.DEPTNO,e.EMPNO,e.ENAME,e.SAL,e.SAL*case when eb.TYPE=1 then 0.1 when eb.TYPE=2 then 0.2 when eb.TYPE=3 then 0.3 end as bonus from EMP e,emp_bonus eb where e.EMPNO=eb.EMPNO and e.DEPTNO=10 ) x,(select DEPTNO,sum(EMP.SAL) as total_sum from EMP where EMP.DEPTNO=10 group by EMP.DEPTNO) d where d.DEPTNO=x.DEPTNO group by x.DEPTNO,d.total_sum
咱们能够经过之查询出sum(x.bonus),而后再外表链接出d.total_sum。
优化一下:
select e.DEPTNO,d.total_sum,sum(e.SAL*case when eb.TYPE=1 then 0.1 when eb.TYPE=2 then 0.2 when eb.TYPE=3 then 0.3 end) as bonus from EMP e,emp_bonus eb,(select DEPTNO,sum(EMP.SAL) as total_sum from EMP where DEPTNO=10 group by DEPTNO) d where e.EMPNO=eb.EMPNO and e.DEPTNO=d.DEPTNO group by e.DEPTNO,d.total_sum
优化的依据是:
出现两个EMP.DEPTNO=10 条件能够合并,第二点就是不必查e.ENAME这些,能够直接合并。
有些人可能使用sum over 函数去写:
select e.DEPTNO,sum(distinct e.SAL) over (partition by e.deptno) as total_sum,sum(e.SAL*case when eb.TYPE=1 then 0.1 when eb.TYPE=2 then 0.2 when eb.TYPE=3 then 0.3 end) over (partition by e.deptno) as bonus from EMP e left join emp_bonus eb on e.EMPNO=eb.EMPNO where e.DEPTNO=10
我上面使用了外链接,是避免这个部门有一部分人若是没有获得bonus。 其中有两个问题,一个就是over 语句中不能包括distinct了,第二个就是不一样人empno 中可能sal相同。 因此这种状况尽可能不要去使用这种方式。