连接查询
实际应用中,一般都是多张表联合查询。
根据表的连接方式划分:
内连接(等值连接,非等值连接,自连接)
外连接 (左外连接,右外连接)
连接查询具有一个现象:笛卡尔积现象
笛卡尔积现象:当两张表进行连接查询时,没有任何条件进行限制,最终的查询结果条数是两张表记录条数的乘积。
select ename,dname from emp,dept;
select e.ename,d.dname from emp e,dept d;(一般用这种方式,别名方式效率高,可读性好。不起别名时,sql会去两个表中查找同一个字段。当两张表存在相同字段时可读性不高)
当加了过滤条件避免了笛卡尔积现象后,不会减少记录的匹配总次数,只不过是显示的是有效记录
select e.ename,d.dname from emp e,dept d where e.deptno = d.deptno; (SQL92语法)
1.内连接之等值连接:最大特点是条件是等量关系(A join B on 连接条件 where...)
select
e.ename,d.dname
from
emp e
inner join (inner可省略)
dept d
on
e.deptno = d.deptno;
该方法优于上述92语法,因为表连接条件和where语法分离出来了,结构更清晰。
2.内连接之非等值连接(最大特点是,连接条件中的关系是非等值关系)
案例:找出员工工资等级
select e.ename,g.grade from emp e join salgrade g on e.sal between g.losal and g.hisal;
3.自连接(最大特点是一张表看作两张表)
案例:找出员工的上级领导
select e.ename, d.ename from emp e join emp d on e.mgr = d.empno;
给一张表起两个别名
4.外连接
什么是内连接?
假设A和B两张表,使用内连接时,将A表和B表能够匹配上的记录查询出来
什么是外连接?
假设A和B两张表,使用外连接时,AB两张表有一张表是主表,一张表是副表,主要查询主表中的数据,捎带查询副表。当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL与之匹配。
外连接分类?
左外连接:左边的表是主表
select
e.ename,d.dname
from
emp e
left outer join (此时左边是主表,outet可省略)
dept d
on
e.deptno = d.deptno;
select e.ename, d.ename from emp e left join emp d on e.mgr = d.empno;
右外连接:右边的表是主表
select e.ename, d.ename from emp d right join emp e on e.mgr = d.empno;
区分内外连接的是left,right,带有这些关键字的一定是外连接。实际场景中外连接用的较多。
外连接重要特点:主表的数据无条件的全部查询出来
找出哪个部门没有员工?
select e.,d. from emp e right join dept d on e.deptno = d.deptno where e.empno is null;
该方法使用另外连接的特点:当副表中的数据没有和主表中的数据匹配上,副表自动模拟出NULL与之匹配。
多表联查
案例1:查询每个员工的部门以及工资等级
select e.ename,d.dname,e.sal,s.grade from emp e join dept d on e.deptno = d.deptno join salgrade s on e.sal between s.losal and s.hisal;
...
A
join
B
on
...
join
C
on
...
表示A先和B连接,然后A再和C连接
案例2:
找出每一个员工的部门名称,工资等级,以及上级领导
select e.ename,d.dname,e.sal,s.grade,el.ename as '领导' from emp e join dept d on e.deptno = d.deptno join salgrade s on e.sal between s.losal and s.hisal left join emp el on e.mgr = el.empno;
子查询
select语句嵌套select语句,被嵌套的语句是子查询
子查询可以出现再哪里?
select
... (select)
from
...(select)
where
...(select)
案例1:
找出高于平均薪资的员工信息
select * from emp where sal > (select avg(sal) from emp);
案例2:找出每个部门平均薪水的薪资等级。
select t.deptno,t.avgsal,s.grade from (select deptno,avg(sal) avgsal from emp group by deptno) t join salgrade s on t.avgsal between s.losal and s.hisal ;
技巧1:查询每个部门的平均薪水,得到的结果当作一个全新的表,连接登记表。
案例3:找出每个部门平均的薪水等级
select e.deptno,avg(s.grade) from emp e join salgrade s on e.sal between s.losal and s.hisal group by e.deptno;
案例4:找出每个员工的名字和所在部门名
select e.ename,(select d.dname from dept d where e.deptno = d.deptno) as dname from emp e;
拓展:union(可以将查询结果相加)
案例:找出工作岗位是salesman 和manager的员工?
select ename,job from emp where job = 'manager' union select ename,job from emp where job = 'salesman';
重点(limit)
limit 是mysql特有的,其他数据库中没有,不通用。
作用:limit取结果集中的部分数据
语法格式:limit startindex ,length
startindex:起始位置
length:表示取几个
案例:去除工资前5名的员工
select ename,sal from emp order by sal desc limit 0,5; (0表示第一条数据)
select ename,sal from emp order by sal desc limit 0,5;(结果同上,startindex可省略,默认为0)
limit为SQL执行的最后一个环节
分页规律:第pageno页:(pageno-1)*pagesize,pagesize