什么是外连接,和内连接有什么区别?
内连接:
假设A和B进行连接,使用内连接的话,凡是A表和B表能够匹配上的记录查询,这就是内连接。
AB两张表没有主副之分,两张表是平等的。
外连接:
假设A和B进行连接,使用外连接的话,AB两张表中有一张表是主表,一张表是副表,主要是查询 主表中的数据,捎带着查询副表,当副表中的数据没有和主表中的数据匹配上,副表自动模拟出N ULL与之匹配。
外连接分类?
左外连接(左连接):表示左边的这张表是主表
右外连接(右连接):表示右边的这张表是主表。
两者都可以互相逆写
找出每个员工的上级领导?(要求所有员工都必须查出上级领导,意为即使上面没有领导也要查出来,但是上面显示为空)
select a.ename as '员工',b.ename as '领导' from emp a join emp b on a.mgr = b.empno;
这样查出来的只有13条记录上面没有领导的就会不显示
改写 左连接,左边的表为主表
select a.ename as '员工',b.ename as '领导' from emp a left (outer) join emp b on a.mgr = b.empno; //outer 可以省略
+--------+-------+
| 员工 | 领导 |
+--------+-------+
| SMITH | FORD |
| ALLEN | BLAKE |
| WARD | BLAKE |
| JONES | KING |
| MARTIN | BLAKE |
| BLAKE | KING |
| CLARK | KING |
| SCOTT | JONES |
| KING | NULL |
| TURNER | BLAKE |
| ADAMS | SCOTT |
| JAMES | BLAKE |
| FORD | JONES |
| MILLER | CLARK |
+--------+-------+
在改写为右连接
select a.ename as '员工',b.ename as '领导' from emp b right (outer) join emp a on a.mgr = b.empno; //outer可以省略
外连接最重要的特点是:主表的数据无条件全部查询出来
查出没有员工的部门?
首先可以想下查出来的表是什么结构,有什么字段名则查什么字段名,比如本次查询希望的是由员工名和部门名,以部门名为主体,当一个部门没有员工的时候则显示为NULL,则要以部门表为主表
select a.dname '部门名',b.ename '员工名' from dept a left join emp b on a.deptno = b.deptno ;
+------------+--------+
| 部门 | ename |
+------------+--------+
| ACCOUNTING | CLARK |
| ACCOUNTING | KING |
| ACCOUNTING | MILLER |
| RESEARCH | SMITH |
| RESEARCH | JONES |
| RESEARCH | SCOTT |
| RESEARCH | ADAMS |
| RESEARCH | FORD |
| SALES | ALLEN |
| SALES | WARD |
| SALES | MARTIN |
| SALES | BLAKE |
| SALES | TURNER |
| SALES | JAMES |
| OPERATIONS | NULL |
+------------+--------+
再加入一个限定语句,筛选出员工为空的部门
mysql> select a.dname '部门',b.ename from dept a left join emp b on a.deptno = b.deptno where ename is null;
+------------+-------+
| 部门 | ename |
+------------+-------+
| OPERATIONS | NULL |
+------------+-------+
三张表怎么连接查询?
案例:找出每一个员工的部门名称以及工资等级?
一个SQL语句在写的时候可以对其进行拆分
第一步在emp表内找员工以及员工部门编号以及工资
select ename,deptno,sal from emp;
+--------+--------+---------+
| ename | deptno | sal |
+--------+--------+---------+
| SMITH | 20 | 800.00 |
| ALLEN | 30 | 1600.00 |
| WARD | 30 | 1250.00 |
| JONES | 20 | 2975.00 |
| MARTIN | 30 | 1250.00 |
| BLAKE | 30 | 2850.00 |
| CLARK | 10 | 2450.00 |
| SCOTT | 20 | 3000.00 |
| KING | 10 | 5000.00 |
| TURNER | 30 | 1500.00 |
| ADAMS | 20 | 1100.00 |
| JAMES | 30 | 950.00 |
| FORD | 20 | 3000.00 |
| MILLER | 10 | 1300.00 |
+--------+--------+---------+
第二步在dept表中找出部门编号及对应的部门
selelct deptno,dname from dept;
+--------+------------+
| deptno | dname |
+--------+------------+
| 10 | ACCOUNTING |
| 20 | RESEARCH |
| 30 | SALES |
| 40 | OPERATIONS |
+--------+------------+
第三步在salgrade表中找出工资等级划分
select * from salgrade;
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
| 1 | 700 | 1200 |
| 2 | 1201 | 1400 |
| 3 | 1401 | 2000 |
| 4 | 2001 | 3000 |
| 5 | 3001 | 9999 |
+-------+-------+-------+
格式:
...
from
A
join
B
on
(判断条件)
join
c
on
判断条件
...
select a.ename,a.sal,b.dname,c.grade
from emp a
join
dept b
on
a.deptno = b.deptno
join
salgrade c
on
a.sal between c.losal and c.hisal
order by
b.dname,a.sal;
//注意是要先让两个表先连,再连下一个表
+--------+---------+------------+-------+
| ename | sal | dname | grade |
+--------+---------+------------+-------+
| MILLER | 1300.00 | ACCOUNTING | 2 |
| CLARK | 2450.00 | ACCOUNTING | 4 |
| KING | 5000.00 | ACCOUNTING | 5 |
| SMITH | 800.00 | RESEARCH | 1 |
| ADAMS | 1100.00 | RESEARCH | 1 |
| JONES | 2975.00 | RESEARCH | 4 |
| FORD | 3000.00 | RESEARCH | 4 |
| SCOTT | 3000.00 | RESEARCH | 4 |
| JAMES | 950.00 | SALES | 1 |
| MARTIN | 1250.00 | SALES | 2 |
| WARD | 1250.00 | SALES | 2 |
| TURNER | 1500.00 | SALES | 3 |
| ALLEN | 1600.00 | SALES | 3 |
| BLAKE | 2850.00 | SALES | 4 |
+--------+---------+------------+-------+
一下是用的比较多的例子,在以后的项目中,掌握这个语句的查询
案例:找出每一个员工的部门名称,工资等级,以及上级领导
select
a.ename as '员工',d.dname,s.grade,b.ename as '上级领导'
from
emp a
join
dept d
on
a.deptno = d.deptno
join
salgrade s
on
a.sal between s.losal and s.hisal
left join
emp b
on
a.mgr = b.empno;
+--------+------------+-------+----------+
| 员工 | dname | grade | 上级领导 |
+--------+------------+-------+----------+
| SMITH | RESEARCH | 1 | FORD |
| ALLEN | SALES | 3 | BLAKE |
| WARD | SALES | 2 | BLAKE |
| JONES | RESEARCH | 4 | KING |
| MARTIN | SALES | 2 | BLAKE |
| BLAKE | SALES | 4 | KING |
| CLARK | ACCOUNTING | 4 | KING |
| SCOTT | RESEARCH | 4 | JONES |
| KING | ACCOUNTING | 5 | NULL |
| TURNER | SALES | 3 | BLAKE |
| ADAMS | RESEARCH | 1 | SCOTT |
| JAMES | SALES | 1 | BLAKE |
| FORD | RESEARCH | 4 | JONES |
| MILLER | ACCOUNTING | 2 | CLARK |
+--------+------------+-------+----------+
3.子查询
3.1、什么是子查询?子查询都可以出现在哪里?
select语句当中嵌套select语句,被嵌套的select语句是子查询。
子查询可以出现在哪里?
select
…(select).
from
…(select).
where
…(select).
3.2、where子句中使用查询
select * from emp where sal >avg(sal); //这个语句是错误的,前面就提到过分组函数会在where执行后才执行,where后不能直接跟avg();所以要用嵌套查询
select * from emp where sal>(select avg(sal) from emp);
3.3from后面嵌套子查询
案例:找出每个部门平均薪水的薪资等级
myself thinking:需要连接薪资水平表,首先找到每个部门的平均薪水,再去划分薪资等级
第一步:找出每个部门的平均薪水
select avg(sal),deptno from emp group by deptno;
+-------------+--------+
| avg(sal) | deptno |
+-------------+--------+
| 2916.666667 | 10 |
| 2175.000000 | 20 |
| 1566.666667 | 30 |
+-------------+--------+
第二步 将以上的查询结果当作临时表t,让t与salgrade进行连接,条件是t.avg(sal) between s.losal and s.hisal
select
t.*,s.grade;
from
(select avg(sal) as avgsal,deptno from emp group by deptno) t //这一步非常重要,括号里面是第一步查出来的表,临时将他当作t,就可以在本次查询中单独当一个表来使用
//这里还需要注意 将avg(sal)换一个别名 不能直接使用其作为字段名进行命令语言键入,否则会查询失败
join
salgrade s
on
t.avgsal between s.losal and s.hisal;
案例找出每个部门平均的薪水等级
第一步:找到每个部门平均的薪水等级(即求每个部门薪水等级的平均值):
select e.ename,e.deptno,s.grade from emp e join salgrade s on e.sal between s.losal and s.hisal;
+--------+--------+-------+
| ename | deptno | grade |
+--------+--------+-------+
| CLARK | 10 | 4 |
| MILLER | 10 | 2 |
| KING | 10 | 5 |
| SMITH | 20 | 1 |
| FORD | 20 | 4 |
| SCOTT | 20 | 4 |
| JONES | 20 | 4 |
| ADAMS | 20 | 1 |
| BLAKE | 30 | 4 |
| JAMES | 30 | 1 |
| ALLEN | 30 | 3 |
| WARD | 30 | 2 |
| TURNER | 30 | 3 |
| MARTIN | 30 | 2 |
+--------+--------+-------+
select后面嵌套子循环
案例:找出每个员工所在的部门名称,要求显示员工名和部门名
这个之前写过,这次换一种方式写
select e.ename,(select d.dname from dept where e.deptno = d.deptno) as dname
from
emp e;
4、unoin(可以将查询结果集相加)
当有两张表没有关系的连接,可以用union来进行连接。
扫描二维码关注公众号,回复:
9313057 查看本文章
案例:找出工作岗位是SALESMAN和MANAGER的员工
写法一:
select ename,job from emp where job ='SALESMAN' or job = 'MANAGER';
写法2:
select ename,job from emp where job in('SALESMAN','MANAGER');
写法3:
select ename,job from emp where job = 'MANAGER'
union
select ename,job from emp where job = 'SALESMAN';