請看圖:
這種狀況咱們通常會使用左鏈接的方式。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相同。 因此這種狀況儘可能不要去使用這種方式。