新增连接查询而不影响其他连接查询

请看图:



这种情况我们一般会使用左连接的方式。

  1. select e.ENAME,d.LOC,eb.RECEIVED
  2. from emp e join dept d
  3. on(e.DEPTNO=d.DEPTNO) left join emp_bonus eb
  4. on(eb.EMPNO=e.EMPNO)
  5. order by 2

上面这种可以实现的,但是不利于我们在写code语句中的复用。

下面是一种标量子查询我的方式,可以帮助我们复用部分sql。

  1. select e.ENAME,d.LOC,(select eb.RECEIVED from emp_bonus eb where e.EMPNO=eb.EMPNO) as RECEIVED
  2. from emp e join dept d
  3. on(e.DEPTNO=d.DEPTNO)
  4. order by 2

这里原理很简单,其实就是先设置了RECEIVED 行然后去查询。

同样这里有限制就是RECEIVED 查询出来必须只有一个结果,因为开辟了一个空间。

在未来第600章中会介绍如果针对查询出多行的问题。

组合使用连接查询与聚合函数

  1. select e.DEPTNO,e.EMPNO,e.ENAME,e.SAL,e.SAL*case
  2. when eb.TYPE=1 then 0.1
  3. when eb.TYPE=2 then 0.2
  4. when eb.TYPE=3 then 0.3
  5. end as bonus
  6. from EMP e,emp_bonus eb
  7. where e.EMPNO=eb.EMPNO
  8. and e.DEPTNO=10

现在只需要看到上图的表。

现在有一个需要,就是要统计上面部门为10的SAL 和 bonus。

这个时候一般想到的是聚合函数。

  1. select x.DEPTNO,sum(x.SAL) as total_sum,sum(x.bonus) as total_bonus from
  2. (select e.DEPTNO,e.EMPNO,e.ENAME,e.SAL,e.SAL*case
  3. when eb.TYPE=1 then 0.1
  4. when eb.TYPE=2 then 0.2
  5. when eb.TYPE=3 then 0.3
  6. end as bonus
  7. from EMP e,emp_bonus eb
  8. where e.EMPNO=eb.EMPNO
  9. and e.DEPTNO=10) x
  10. group by x.DEPTNO

得到的结果为错误的。因为有人得到两次奖励:



那么可能会这样写:

  1. (select e.DEPTNO,e.EMPNO,e.ENAME,e.SAL,e.SAL*case
  2. when eb.TYPE=1 then 0.1
  3. when eb.TYPE=2 then 0.2
  4. when eb.TYPE=3 then 0.3
  5. end as bonus
  6. from EMP e,emp_bonus eb
  7. where e.EMPNO=eb.EMPNO
  8. and e.DEPTNO=10) x
  9. group by x.DEPTNO

排除掉sal中相同的项增加,但是万一有人sal相同怎么办?这肯定是一个问题。还有一个问题就是如果这个部门有一部分人如果没有得到bonus怎么办?也就是说有一部分SAL没显示出来

  1. select x.DEPTNO, d.total_sum,sum(x.bonus) as total_bonus from
  2. (select e.DEPTNO,e.EMPNO,e.ENAME,e.SAL,e.SAL*case
  3. when eb.TYPE=1 then 0.1
  4. when eb.TYPE=2 then 0.2
  5. when eb.TYPE=3 then 0.3
  6. end as bonus
  7. from EMP e,emp_bonus eb
  8. where e.EMPNO=eb.EMPNO
  9. and e.DEPTNO=10
  10. ) x,(select DEPTNO,sum(EMP.SAL) as total_sum from EMP where EMP.DEPTNO=10 group by EMP.DEPTNO) d
  11. where d.DEPTNO=x.DEPTNO
  12. group by x.DEPTNO,d.total_sum

我们可以通过之查询出sum(x.bonus),然后再外表连接出d.total_sum。

优化一下:

  1. select e.DEPTNO,d.total_sum,sum(e.SAL*case
  2. when eb.TYPE=1 then 0.1
  3. when eb.TYPE=2 then 0.2
  4. when eb.TYPE=3 then 0.3
  5. end) as bonus
  6. from EMP e,emp_bonus eb,(select DEPTNO,sum(EMP.SAL) as total_sum from EMP where DEPTNO=10 group by DEPTNO) d
  7. where e.EMPNO=eb.EMPNO and e.DEPTNO=d.DEPTNO
  8. group by e.DEPTNO,d.total_sum

优化的依据是:

出现两个EMP.DEPTNO=10 条件可以合并,第二点就是没必要查e.ENAME这些,可以直接合并。

有些人可能使用sum over 函数去写:

  1. select e.DEPTNO,sum(distinct e.SAL) over (partition by e.deptno) as total_sum,sum(e.SAL*case
  2. when eb.TYPE=1 then 0.1
  3. when eb.TYPE=2 then 0.2
  4. when eb.TYPE=3 then 0.3
  5. end) over (partition by e.deptno) as bonus
  6. from EMP e left join emp_bonus eb on e.EMPNO=eb.EMPNO
  7. where e.DEPTNO=10

我上面使用了外连接,是避免这个部门有一部分人如果没有得到bonus。

其中有两个问题,一个就是over 语句中不能包括distinct了,第二个就是不同人empno 中可能sal相同。

所以这种情况尽量不要去使用这种方式。

sql 语句系列(多表之链)[八百章之第三章]的更多相关文章

  1. sql 语句系列(null 值处理)[八百章之第二章]

    查找只存在一个表中的数据 有两张表: EMP: select * from emp DEPT: 他们有共同的属性:deptno 现在要查询EMP 中的deptno不等于DEPTNO的deptno项. ...

  2. oracle一条sql语句统计充值表中今天,昨天,前天三天充值记录

    select NVL(sum(case when create_date_time>=to_date('2014-11-24 00:00:00','yyyy-mm-dd hh24:mi:ss') ...

  3. sql语句中----删除表数据drop、truncate和delete的用法

    sql语句中----删除表数据drop.truncate和delete的用法 --drop drop table  tb   --tb表示数据表的名字,下同 删除内容和定义,释放空间.简单来说就是把整 ...

  4. SQL语句查询某表的所有字段及数据类型

    SQL语句查询某表的所有字段及数据类型 SELECT name AS column_name , TYPE_NAME(system_type_id) AS column_type , max_leng ...

  5. (转载)用SQL语句创建Access表

    <来源网址:http://www.delphifans.com/infoview/Article_220.html>用SQL语句创建Access表 很久以前弄的,用了一天的时间,没有什么技 ...

  6. 使用sql语句获取数据库表的信息

    下面的sql语句可以查看表的信息.其中modify_date和create_date可以根据表的修改时间来查看.如果不需要删除后,就能看到所有表的字段信息 ) PERCENT d.name AS 表名 ...

  7. [转]关于oracle sql语句查询时表名和字段名要加双引号的问题

    oracle初学者一般会遇到这个问题.   用navicat可视化创建了表,可是就是不能查到!   后来发现②语句可以查询到 ①select * from user; 但是,我们如果给user加上双引 ...

  8. SQL语句之 多表管理

    SQL语句之 多表管理 一个数据库内通常会有不止一张表,有时候我们要把多张表联系起来,这就需要用到多表管理的语句. 1.外键约束 一个表中的非主键字段,如果在另外一张表中是主键,那么这个字段我们叫它做 ...

  9. ylb:sql语句重命名表名和列名

    ylbtech-SQL Server:SQL Server-sql语句重命名表名和列名 sql语句重命名表名和列名 ylb:sql语句重命名表名和列名 返回顶部 一.更改数据库名    sp_rena ...

随机推荐

  1. 用VS2013进行调试

    首先新建一个简单的C++程序 打开VS2013-文件-新建-项目-选择Win32 控制台程序 添加-新建项-选择C++源文件 编写如下代码 #include<iostream> using ...

  2. 吴裕雄--天生自然 oracle学习笔记:oracle理论学习详解及各种简单操作例子

    1. 数据库的发展过程 层次模型 -->网状模型 -->关系模型 -->对象关系模型 2. 关于数据库的概念 DB:数据库(存储信息的仓库) DBMS:数据库管理系统(用于管理数据库 ...

  3. 手机视频APP将关闭 生态梦成空的三星如何自救?

    生态梦成空的三星如何自救?"> 三星如今的处境,只能用"屋漏偏逢连夜雨"来形容.继营收.利润.智能手机销量等大幅下滑之后,裁员也接踵而来,股价的下跌也自然在情理之中 ...

  4. androidthreadtest<CODE 2 chaper9>

    学习目的:1.了解android线程的使用 2.了解主线程与子线程区别 3.解析异步处理机制主线程与子线程:所谓主线程,在Windows窗体应用程序中一般指UI线程,这个是程序启动的时候首先创建的线程 ...

  5. Zookeeper的使用场景和集群配置

    Zookeeper的介绍 ZK在分布式系统的应用 Zookeeper搭建 集群角色介绍 ZK的常用命令 一.Zookeeper的介绍 官方:ZooKeeper是一个分布式的,开放源码的分布式应用程序协 ...

  6. KEMET推出新的多层陶瓷电容器,用于市电供电的应用

    前言:2019年12月2日,全球领先的电子组件供应商KEMET公司 (“ KEMET”或“公司”)推出了一系列新的表面安装设备(SMD)安全认证的多层陶瓷电容器(MLCC),用于市电供电的应用.与现有 ...

  7. python2.7.6安装easy_install (windows 64 环境)

    1.复制以下代码保存到easy_install.py文件中(文件名可随意命名)并将该文件放到python的安装路径中(如:D:\Python27) #!/usr/bin/env python &quo ...

  8. 用ABAP 生成二维码 QR Code

    除了使用我的这篇blogStep by step to create QRCode in ABAP Webdynpro提到的使用ABAP webdynpro生成二维码之外,也可以通过使用二维码在线生成 ...

  9. Python读取和写入文件

    1 从文件中读取数据 1.1 读取整个文件 创建名为test的txt文本文件,添加内容如下所示: 123456789023456789013456789012 实现代码: with open('tes ...

  10. mysql从5.5升级到5.7遇到的坑

    在安装mysql5.7时很顺利安装完成,但在启动项目时报错: [Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clau ...