第三章 多表查询
问题:如何查询员工的编号、姓名、薪水和部门编号、部门名称?
方法1:多条sql语句,先从员工表查询员工的编号、姓名、薪水,然后从部门表查询部门编号、部门名称。
方法2:单条sql语句查询
一、多表查询
1、交叉连接
交叉连接查询:(笛卡尔积:两张表的所有情况全部组合在一起)
缺点:没有实际意义,只有理论意义,让我们了解连接的原理
语法:select * from 表1 join 表 2;
SELECT * FROM dept JOIN empolee;
2、自然连接
会自动的匹配所有的同名列,并且同列名只保留一份。
语法:select * from 表1 natural join 表2;
SELECT * FROM dept NATURAL JOIN empolee;
没有指定表名,NATURAL关键字会自动匹配
SELECT empno,ename,sal,dno,dname FROM dept NATURAL JOIN empolee;
指定表名,提升查询效率
SELECT empolee.empno,empolee.ename,empolee.sal,dept.dno,dept.dname FROM dept NATURAL JOIN empolee;
表名太长,给表起别名
SELECT e.empno,e.ename,e.sal,d.dno,d.dname FROM dept as d NATURAL JOIN empolee as e;
3、using子句
自然连接匹配的是全部同名列,using子句给定需要匹配的同名列,按照给定同名列进行匹配。
语法:select * from 表1 join 表2 using(同名列);
SELECT e.empno,e.ename,e.sal,d.dno,d.dname FROM dept AS d JOIN empolee AS e USING(dno);
-- USING(dno)等价于 e.dno = d.dno
缺点:using子句和自然连接必须有相同的列,如果两张表的主键,外键的名称不一样,就无法使用自然连接和using子句
4、on子句
on子句解决了以上的全部问题,选用on子句即可
SELECT e.empno,e.ename,e.sal,d.dno,d.dname FROM dept AS d JOIN empolee AS e on e.dno=d.dno;
语法:select * from 表1 join 表2 on( 条件);(条件一般是指表1和表2的限制条件)
以上的四种连接都属于内连接。
二、内连接和外连接
1、内连接:只是显示匹配的数据(笛卡尔积)
SELECT e.empno,e.ename,e.sal,d.dno,d.dname FROM dept AS d JOIN empolee AS e on (e.dno=d.dno);
2、外连接:可以显示部分或者全部匹配的数据
1)左外连接
left outer join还可以显示左表的未匹配的部分数据或者全部数据。
语法:select * from 表1 left outer join 表2 on (条件);
SELECT e.empno,e.ename,e.sal,d.dno,d.dname FROM dept AS d LEFT OUTER JOIN empolee AS e ON (e.dno=d.dno);
2)右外连接
right outer join还可以显示右表的未匹配的部分数据或者全部数据。
语法:select * from 表1 right outer join 表2 on (条件);
SELECT e.empno,e.ename,e.sal,d.dno,d.dname FROM dept AS d RIGHT OUTER JOIN empolee AS e ON (e.dno=d.dno);
3)全连接(mysql不支持,oracle支持)
full outer join还可以显示右表的未匹配的部分数据或者全部数据。
mysql解决方案:(左外连接+右外连接的并集)
select * from 表1 left outer join 表2 on (条件) union select * from 表1 right outer join 表2 on (条件);
备注:
union:去重(效率低)
union all:不去重(效率高)
三、三表查询
1、解决方案
双表查询——》单表——》双表查询
2、案例
问题:查询员工的编号、姓名、薪水(员工表);部门、部门名称(部门表);薪水等级(薪水等级)。
select e.empno,e.ename,e.esal,d.dno,d.dname,sg.grade from empolee left out join dept on (e.dno=d.dno)
left out join salgrade on(e.sal between sg.lowsal and sg.hihsal);
四、自连接查询
自连接用于同一张表的连接查询处理。实质上每查询一次都会产生一章临时表。
1、解决方案
把一张表看作多张表。本表——》临时表——》本表。
2、案例
查询员工的编号、姓名和上级的编号以及姓名;
SELECT t.`empno` '员工编号',t.`ename` '姓名',e.`mrg_id` '上级编号',e.`ename` '上级姓名' FROM empolee AS t LEFT OUTER JOIN empolee e ON (t.mrg_id = e.dno);