当我们要查询的数据要使用的限制条件不是很简单的时候,可能要在一个限制条件下再次限制,比如要查找小美所在公司的平均薪资,就要先找到小美的公司,再求平均薪资。复合查询分三种,多表连接查询、子句查询和合并查询。
本文要使用的数据库scott的三张表:
多表连接查询
多表连接就是将多个表作笛卡尔积,简单来说,就是将每个表的每一行依次组装起来。例如A,B表连接,会先将A表的第一行数据与B表的每一行数据组装,再从A表的第二行开始与B每一行组装,以此类推。所以最后组装好的表的行数为A的行数*B的行数。
我们在使用中一般会使用where条件来消除无效数据。例如,我们想知道每个员工的工作地点,就要将emp表和dept表连接,两个表中deptno相同的行就是有效数据:
不同表之间可以连接,表自身也可以和自己连接。例如,我们想要知道每个员工的管理者是谁,emp表中的每个员工数据中都会有mgr,即该员工的管理者的工号,我们可以将两个emp表连接,第一个表的mgr和第二个表的empno相同的为有效数据,(注意此时表的名字要重命名):
内外连接
多表连接分为内连接和外连接,上面我们使用where对连接后的表数据做筛选其实就是内连接。
内连接的标准写法是这样的:
select 列名... from 表1 inner join 表2 on 连接条件;
外连接分为左外连接和右外连接:
--左连接
select 列名... from 表1 left join 表2 on 连接条件;
--有连接
select 列名... from 表1 right join 表2 on 连接条件;
那么这三者有什么区别呢?
我们考虑到在两个表间存在某些数据,只在一个表中出现,另一个表中不存在或者为null。 在这种情况下,内连接的处理是,丢弃这些数据;左连接会以表1为主表,表一中出现而表二没出现的,会在连接后的数据的表二部分补null;右连接会以表2为主表,表二出现而表一没出现的,会在连接后数据的表一部分补null。
例子:设计两个表,学生表和成绩表,但是学生表和成绩表中的数据并不都是一一对应的。
子句查询
子句查询就是在一个语句中嵌套使用select语句,也叫嵌套查询。
根据子句所在位置有两种:在where条件语句中,本文简称where子句查询,还可以在from中,本文简称from子句查询。
where子句查询
根据嵌套的select子句返回的记录可以分为三类:单行子查询,多行子查询和多列子查询。
单行子查询
子句返回一行记录。select后面只有一个列,且该列数据中满足where条件的只有一个。
查找SMITH所在部门的其他员工:
多行子查询
字句返回多行记录。select后面只有一个列,且该列数据中满足where条件的不止一个。
in关键字,查找列中数据是否在集合中;查询其他部门中与10号部门存在的工作岗位相同的雇员的信息,但是不包含10号部门的雇员:
all关键字;显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号:
any关键字;显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门 的员工)
这个问题也可以理解为找薪资大于部门30中最低的薪资的员工,和上面的结果一样:
多列子查询
查询返回多个列数据的子查询语句。select后面有多个列
案例:查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人
from子句查询
其实select子句本质就是返回一张临时表,包括我们每次查询的显示在屏幕上的结果就是一张表。所以我们可以用from子句获得的临时表与其他表作多表连接查询。注意:临时表必须指定一个名字。
案例1,显示每个高于自己部门平均工资的员工信息:
select emp.ename,emp.deptno
from emp,(select deptno,avg(sal) average from emp group by deptno) tem
where emp.deptno=tem.deptno and emp.sal>average;
分析:先用子句按部门号分组,获取各部门平均薪资,再将这个表与emp连接,最后使用where条件筛选。
合并查询
使用合并查询的前提是,两个结果集的列相同。
union
获取两个结果集的并集,并去除结果集中重复的行。
将工资大于25000或职位是MANAGER的人找出来:
union all
获取两个结果集的并集,但是不去除去除结果集中重复的行。
将工资大于25000或职位是MANAGER的人找出来:
可以发现这次的结果会发生重复,与上一个不加all的合并查询结果不同。