sql 语句系列(多表之链)[八百章之第三章]

新增链接查询而不影响其余链接查询

请看图:

这种状况咱们通常会使用左链接的方式。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相同。 因此这种状况尽可能不要去使用这种方式。

相关文章
相关标签/搜索