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 查询出来必须只有一个结果,因为开辟了一个空间。
在未来第600章中会介绍如果针对查询出多行的问题。
组合使用连接查询与聚合函数
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
现在只需要看到上图的表。
现在有一个需要,就是要统计上面部门为10的SAL 和 bonus。
这个时候一般想到的是聚合函数。
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 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相同。
所以这种情况尽量不要去使用这种方式。
sql 语句系列(多表之链)[八百章之第三章]的更多相关文章
- sql 语句系列(null 值处理)[八百章之第二章]
查找只存在一个表中的数据 有两张表: EMP: select * from emp DEPT: 他们有共同的属性:deptno 现在要查询EMP 中的deptno不等于DEPTNO的deptno项. ...
- oracle一条sql语句统计充值表中今天,昨天,前天三天充值记录
select NVL(sum(case when create_date_time>=to_date('2014-11-24 00:00:00','yyyy-mm-dd hh24:mi:ss') ...
- sql语句中----删除表数据drop、truncate和delete的用法
sql语句中----删除表数据drop.truncate和delete的用法 --drop drop table tb --tb表示数据表的名字,下同 删除内容和定义,释放空间.简单来说就是把整 ...
- SQL语句查询某表的所有字段及数据类型
SQL语句查询某表的所有字段及数据类型 SELECT name AS column_name , TYPE_NAME(system_type_id) AS column_type , max_leng ...
- (转载)用SQL语句创建Access表
<来源网址:http://www.delphifans.com/infoview/Article_220.html>用SQL语句创建Access表 很久以前弄的,用了一天的时间,没有什么技 ...
- 使用sql语句获取数据库表的信息
下面的sql语句可以查看表的信息.其中modify_date和create_date可以根据表的修改时间来查看.如果不需要删除后,就能看到所有表的字段信息 ) PERCENT d.name AS 表名 ...
- [转]关于oracle sql语句查询时表名和字段名要加双引号的问题
oracle初学者一般会遇到这个问题. 用navicat可视化创建了表,可是就是不能查到! 后来发现②语句可以查询到 ①select * from user; 但是,我们如果给user加上双引 ...
- SQL语句之 多表管理
SQL语句之 多表管理 一个数据库内通常会有不止一张表,有时候我们要把多张表联系起来,这就需要用到多表管理的语句. 1.外键约束 一个表中的非主键字段,如果在另外一张表中是主键,那么这个字段我们叫它做 ...
- ylb:sql语句重命名表名和列名
ylbtech-SQL Server:SQL Server-sql语句重命名表名和列名 sql语句重命名表名和列名 ylb:sql语句重命名表名和列名 返回顶部 一.更改数据库名 sp_rena ...
随机推荐
- haproxy笔记之四:配置文件中的关键字参考
3.1 balance balance <algorithm> [ <arguments> ]balance url_param <param> [check_po ...
- Nginx笔记总结五:Nginx配置虚拟主机
upstream proxy1 { server ; } upstream proxy2 { server ; } server { listen ; server_name www1.dlab.co ...
- 吴裕雄--天生自然 PYTHON数据分析:医疗数据分析
import numpy as np # linear algebra import pandas as pd # data processing, CSV file I/O (e.g. pd.rea ...
- Python---3基础输入方法
一字符串写法 1.单一字符串 用print()在括号中加上字符串,就可以向屏幕上输出指定的文字.比如输出'hello, world',用代码实现如下: >>> print('hell ...
- SolrJ 的运用
SolrJ 是操作 Solr 的 Java 客户端,它提供了增加.修改.删除.查询 Solr 索引的 Java 接口.SolrJ 针对 Solr 提供了 REST 的 Http 接口进行了封装, So ...
- Android注解支持Support Annotations详解
###注解支持(Support Annotations)Android support library从19.1版本开始引入了一个新的注解库,它包含很多有用的元注解,你能用它们修饰你的代码,帮助你发现 ...
- 使用python抓取汽车之家车型数据
import requests import pymysql HOSTNAME = '127.0.0.1' USERNAME = 'root' PASSWORD = 'zyndev' DATABASE ...
- Enbale IE mode in Edge
1. 打开Edge, 在地址栏输入 edge://flags/ 2. 搜索 Enable IE Integration , 配置为 IE mode 3. 找到Edge的启动程序路径.如 C:\Prog ...
- php-fpm启动失败处理
报错信息: No pool defined. at least one pool section must be specified in config file [11-Mar-2019 23:57 ...
- swoole(6)Task异步任务
一:什么是task进程? task进程是独立与worker进程的一组进程 ,他主要处理耗时较长的业务逻辑,并且不影响worker进程处理客户端的请求.worker进程通过task()函数把数据投递到 ...