连接查询(外连接)(三张表连接查询)

什么是外连接,和内连接有什么区别?
内连接:
假设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';
	
	
发布了28 篇原创文章 · 获赞 0 · 访问量 438

猜你喜欢

转载自blog.csdn.net/wenshao007/article/details/104342217