mysql多表查询和内外连接

多表查询

有时候我们要查找的信息在两个表里,还是拿经典测试表举例。
在这里插入图片描述
现在想筛选出相同部门的员工,并显示它们的员工名,部门号和部门名。

我们发现,员工名和部门号都在emp这张表中,但是部门名在dept这张表。因此我们要进行多表查询。

多表查询的语法很简单,就是from后面接不同的表名即可。
from a, b, c, ...

mysql中select * from a, b,c返回的时候是怎么返回的呢?
最终返回的表如图:这种叫笛卡尔积。
在这里插入图片描述

因此要在多表查询中查到我们想要的信息,就必须要进行筛选。


回到刚刚那个题目:
我们首先需要筛选的信息就是emp表的deptno应该要等于dept表的deptno,因为一个员工不可能既是A部门,又是B部门。

加上where emp.deptno = dept.deptno即可
需要说的就是由于多表中有可能有很多相同名字的列,比如emp表有deptno,dept表也有deptno。因此为了防止混淆,用表名.列来区分

在这里插入图片描述
原理讲完了,开始做题

显示部门号为10的部门名,员工名和工资

这题很简单,在上一个例子的基础上加上一个and条件就好了
在这里插入图片描述

显示各个员工的姓名,工资,及工资级别

工资只能是一个级别的,因此用工资来筛选即可。
工资在级别对于的范围,就符合条件。
sal between losal and hisal
在这里插入图片描述

自连接

所谓自连接就是自己和自己笛卡尔积之后得到的表

例子:
显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号–empno)

有两种方法:
1.直接查
筛选条件就是ford的mgr编号等于empno
在这里插入图片描述
在这里插入图片描述

2.用自连接
注:这里不能加上a.empno = b.empno,加上了自连接就白连了,又变回单表了
在这里插入图片描述

嵌套查询

嵌套查询有多行单列和单行多列。

单行单列子查询

之前写的全是这种单行子查询

单行子查询是指第二个select返回一行的记录
举个例子:
select * from EMP WHERE deptno = (select deptno from EMP where ename=‘smith’);

第二个select其实就是把ename = smith的那一行返回了。

多行单列子查询

后面的select返回多行单列记录。
相当于返回了一个集合,然后再从这个集合当中选数据。用三个关键字选,分别是in,all,any

in(存在于集合内)

查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的

相当于从集合(所有10号部门的工作岗位)中挑选数据。怎么挑选呢?
挑选那些工作和集合内元素相同的人。
最后再把属于集合内的人筛掉即可。

在这里插入图片描述

all(比集合里所有元素大/小)

显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号

由于部门30的所有员工的工资是多行数据,因此也是一个集合
在这里插入图片描述

any(比集合内任意一个大/小)

显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工)

在这里插入图片描述

多列单行子查询

子查询一定是返回单行,否则会报错的。
在这里插入图片描述

语法(多列数据) = (多列数据)

查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人
在这里插入图片描述

在from中使用子查询(多表查询+子查询 + group by)

子查询是集合,集合其实就是一张表。因此可以让from从表中查找数据
模板:
select xxxx from xxx (select xxx,xxx from xxx group by xxx) where xxx

例子:显示每个高于自己部门平均工资的员工的姓名、部门、工资、部门平均工资

这个题挺难的。
在这里插入图片描述
先说答案:
select ename, deptno, sal, asal from EMP,
(select avg(sal) asal, deptno dt from EMP group by deptno) tmp
where EMP.sal > tmp.asal and EMP.deptno=tmp.dt;

由于要求平均工资,因此要用avg函数,由于avg函数是聚合函数,聚合函数只有一行,不能和这些多行的数据放在同一张表里面。

因此要求avg必须得根据部门号去group by deptno求,并生成一张新表。再从这两张新表多表查询,筛选出答案。

需要注意的一点是,前面select 必须写成asal,不能写成avg(sal).原因就是刚刚说的avg是聚合函数,不能直接这么用。


第二道题目:查找每个部门工资最高的人的姓名、工资、部门、最高工资
select EMP.ename, EMP.sal, EMP.deptno, ms from EMP,
(select max(sal) ms, deptno from EMP group by deptno) tmp
where EMP.deptno=tmp.deptno and EMP.sal=tmp.ms;
在这里插入图片描述
这道题和上面是一样的。


第三道题目:显示每个部门的信息(部门名,编号,地址)和人员数量
在这里插入图片描述
select dname, deptno, loc, cnt from dept,
(select deptno dt, count(deptno) cnt from emp group by deptno) tmp where dept.deptno = tmp.dt;

其实可以说都是同样的模板了。

合并查询

union(并集+去重)

对两个集合求并集,会自动去掉结果集中的重复行。
将工资大于2500或职位是MANAGER的人找出来

常规做法:
在这里插入图片描述
union做法:因为是或,因此可以用并集
在这里插入图片描述

union all(并集不去重)

用法和union一样,但是不去重。
在这里插入图片描述

内外连接

内连接

语法
select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件;

SQL查询中各个关键字的执行先后顺序 from > on> join > where > group by > with > having > select > distinct > order by > limit。

where写法
select ename, dname from EMP, DEPT where EMP.deptno=DEPT.deptno and ename=‘SMITH’;

on写法
select ename, dname from EMP inner join DEPT on EMP.deptno=DEPT.deptno where ename=‘SMITH’;
(用on就一定要用inner join)

关于on和where的区别:我们可以发现on的执行顺序要先于where,因此我们可以理解成,在进行笛卡尔积的时候,如果用on进行连接的话,on并没有让两个表全部连接,而是只把正确的部分连接起来了。

如果使用where的话,它做的是筛选的工作。表是被完整的连接出来之后,根据where的条件来筛选出结果的。

注:前面写的from a, b就是内连接,只不过是全内连接

外连接

分为左外连接和右外连接

左外连接

如果联合查询,左侧的表完全显示我们就说是左外连接

select 字段名 from 表名1 left join 表名2 on 连接条件

使用场景:比如一场考试,有一张学生表,一张考试成绩表(没有成绩的同学不在里面),现在要显示所有学生的成绩信息。(包括没成绩的)

如果使用
select stu.id, name, score from stu inner join exam on stu.id = exam.id

看起来好像没什么问题,但是如果exam表里面没有成绩的同学就不存进去了,那么使用内连接的话,没有成绩的同学就无法显示出来了。

这个时候就要使用左外连接了,保证所有学生的信息都要显示出来。
select stu.id, name, score from stu left join exam on stu.id = exam.id

右连接是同理的。

列出部门名称和这些部门的员工信息,同时列出没有员工的部门

分析:很明显是dept表和emp表连接,它又要求同时列出没有员工的部门,因此要把dept变成左连接,保证全部显示。

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值