二、多表联合查询
1、合并结果集 : 把两个select语句的查询结果合并到一起
union 合并结果集并且去除重复数据。
union all合并结果集并且不去除重复数据
要求:被合并的两个结果集,列数和列类型必须相同
2、连接查询 : 就是求多个表的乘积
例如 a表连接b 表那么查询结果就是a表*b表
连接查询产生 笛卡尔积(在sql 中实现方式,交叉连接 cross join)
所有的连接方式都会产生笛卡尔积,然后加上限制条件,才会有实际查询意义
jion 就是把多个表连接成一个表的手段
多表查询分为 内连接和外连接
select empt .ename,dept .dname,empt .job from empt as e,dept as d where empt .deptno=dept .deptno;
select e.ename,d.dname,e.job from empt as e,dept as d where e.deptno=d.deptno;
AS 关键字可以给表起别名 as 可以省略
内连接 【inner】join...on inner可省略
【隐式】 select e.ename,d.dname,e.job from empt as e,dept as d where e.deptno=d.deptno;
【显式】select e.ename,d.dname,e.job from empt as e inner join dept d on e.deptno=d.deptno;
特点: 查询结果必须是满足条件的
外连接 【outer】join...on outer可省略
左连接 :以左表为主,先查询出左表,然后查询右表,右表中满足条件的显示,不满足条件的显示为null
例如:SELECT * FROM emp e LEFT OUTER JOIN dept d ON e.deptno = d.deptno;
右连接:右表为主,先查出右表,在查询左表,左表中满足条件的显示,不满足条件的显示为null
SELECT * FROM emp e RIGHT OUTER JOIN dept d ON e.deptno = d.deptno;
总结:
1、如果sql用的是Left join
- on后面条件对left 表没作用,只是对right 表起过滤作用
- where 语句可以对生成临时表后起到过滤,相当于过滤了left表
2、如果sql用的是right join
- on后面条件对right 表没作用,只是对left 表起过滤作用
- where 语句可以对生成临时表后起到过滤,相当于过滤了right 表
在使用left join时 on 和where区别如下:
1、on条件条件是否为真,是在 生成临时表时使用的条件,不管on的为真,都会返回左边表的数据
2、where条件在生成临时表后,再对临时表进行过滤,如果条件不为真,就会全部过滤。
自然连接 :natural join
自然连接 无需你去给出外键关联等式,它会自动找到这一等式。两张连接表中,名称和类型完全一致的列作为条件。
SELECT * FROM emp NATURAL JOIN dept;
SELECT * FROM emp NATURAL LEFT JOIN dept;
SELECT * FROM emp NATURAL RIGHT JOIN dept;
总结:
连接查询时,sql查询的核心,按照实际需求来选择对应的类型。
如果选择不当,非但不能提高效率,反而会带来一系列的逻辑错误,甚至性能会下降。
选择依据:
- 查两张表关联列 相等的数据,用内连接
- right表时left的子集,用左外连接
- left表是right的子集,用右外连接
- right和left 彼此之间的交集,但是互不为子集,使用全外连接
3、子查询
一个select语句中 包含另一个完整的select语句,子查询 就是 嵌套查询
1)、单行单列 (用于条件)
例如 :员工表中 工资高于CLARK的员工都有谁
分析 :
1.查询CLARK的工资 select sal from emp where ename="CLARK"2.查询高于CLARK的员工 select * from emp where sal > 第一步的结果
3.结论 select * from emp where sal > (select sal from emp where ename="CLARK")
2)、单行多列 (用于条件)
例如 :查询员工表中 工作 和 工资 与 MARTIN完全相同的员工信息分析 :
1.查询MARTIN的工作和工资 select job,sal from emp where ename="MARTIN"
2.查询与MARTIN工作和工资相同的人 select * from emp where (job,sal) in 第一步的结果
3.结论 select * from emp where (job,sal) in (select job,sal from emp where ename="MARTIN")
3).多行单列 (用于条件)
多行子查询 返回多行数据
在where 使用多行子查询时 要用 all any in
例如 :查找工资高于30号部门所有人的 员工
分析 :
1.查找30号部门所有人的工资 select sal from emp where deptno=30;
2.查找高于30号部门所有人工资的员工信息 select * from emp where sal > all 第一步的结果
3.结论
SELECT * FROM emp WHERE sal > ALL (SELECT sal FROM emp WHERE deptno=30);SELECT * FROM emp WHERE sal > ANY (SELECT sal FROM emp WHERE deptno=30);
/*练习 部门编号为20的员工工资 并且 大于部门编号为30的所有人工资的 员工列表*/
SELECT * FROM emp WHERE deptno=20 AND sal> ALL(SELECT sal FROM emp WHERE deptno=30)
4).多行多列 (表)
例如 :查询员工编号为7788的员工 姓名 工资 部门名称 部门地址
分析 :涉及到 emp dept两张表
1.查询 姓名 和 工资
select ename,sal from emp where empno=7788
2.查询 部门名称 和 部门地址
select e.ename,e.sal,d.dname,d.loc
from emp e,dept d
where e.deptno = d.deptno and e.empno=7788
改版:
select e.ename,e.sal,d.dname,d.loc
from emp e,(select dname,loc,deptno from dept) d
where e.deptno = d.deptno and e.empno=7788
/*练习 求7369员工 姓名 经理姓名 经理编号 自己连接自己*/
SELECT e1.ename,e2.ename,e2.empno
FROM emp e1,(SELECT empno,ename FROM emp) e2
WHERE e1.mgr = e2.empno AND e1.empno = 7369