前提
本篇博客,我将通过讲解例题的方式,带大家进一步掌握多表查询的使用规则和使用技巧
正文
前提
先建好表 表1 salgrade (薪资等级表) 表2 emp(员工信息表) 表3 dept(部门信息表),插入相关数据,我使用DataGrip 图像化界面工具,使用SQL语句,来操作。
表1 salgrade (薪资等级表)
grade 等级,losal 最低工资,hisal 最高工资
注意,表1 中添加主键约束 id 和 表1 dept_id 表2 id 是外键约束关系
表2 emp (员工信息表)
job 职位,salary 薪资 , entrydate 入职时间 managerid 直属领导 ,dept_id 工作位置编号
由于我在建完表后,添加外检约束后,再插入数据。这一过程中,总是报违法外检约束错误,所以我将emp 表中的dept_id 全部设置为 null,后面再做更改
更改的语法:update 表名 set 字段=值 where条件;
表3 dept(部门信息表)
id 编号,name 工作地方名字
例题
1 查看员工的姓名,年龄,职位,部门信息(隐式内连接)
思路,该题涉及2 张表 emp(员工信息表) dept(部门信息表),同时还要使用隐式内连接
内连接:两张表取交集,也就是公共数据的部分
我们知道,内连接分为两种 隐式内连接,显示内连接
隐式内连接语法:select 字段列表 from 表1, 表2 where 连接条件 and 其他条件;
连接条件:两张表中有联系的字段之间的组合比如通常是表1.id=表2.id。这样的形式。
显示内连接语法:select 字段列表 from 表1 (inner) join 表2 on 连接条件 where 条件;
代码如下
select e.name ,e.age ,e.job,d.name from emp e,dept d where e.dept_id =d.id ;
2 查询 年龄小于 30 岁的员工的姓名,年龄,职位,部门信息( 显示内连接)
思路:本题使用 emp表(员工信息表) dept表(部门信息表),同时要求使用显示内连接
内连接:两张表取交集,也就是公共数据的部分
显示内连接语法: select 字段列表 from 表1(inner) join 表2 on 连接条件 where 条件;
代码如下
select e.name ,e.age ,e.job,d.name from emp e join dept d on e.dept_id =d.id where e.age <30;注意:如果出现重复数据,可以使用distinct 去重。
3 查询 所有年龄大于30 岁的员工,及其归属的部门,如果员工没有分配部门,也要显示
由于,现在的emp表中没有 员工,未分配部门,所以,我重新添加了数据
insert into emp values ( 9,'田明',42,'职员',26000,'2000-10-1',4,null),(10,'轩龙',39,'职员',20000,'2000-1-1',4,null );
思路:本题,使用 表1 emp ,表2 dept 。条件是年龄大30 ,同时还要查询没有分配的员工信息,所以使用外连接
外连接:两张表取任意一张表的全部,当然还包括他们公共的部分。
根据外连接查询的结果,分为左外连接,右外连接
左外连接语法:select 字段列表 from 表1 left join 表2 on 连接条件 where 条件
提示:我们查询的是 left 左边的表 ,也就是表1.
右外连接语法:select 字段列表 from 表1 right join 表2 on 连接条件 where 条件
提示:我们查询的是 表1 right ,也就是表2 。
代码如下
select e. *,d2 .name from emp e left join day02.dept d2 on d2.id = e.dept_id where e.age >30;
4查询所有员工的工资等级
思路 :本题使用了 emp表, salgrade (薪资等级表)我们要查询员工的工资等级,就要知道这两张表的关系,如要知道工资等级,就是要通过比较 salgrade 中最小值和最大值,通过比较他们,来判断,是在哪一等级。
连接条件:emp.salary >=salgrade .losal and emp.salary <=salgrade.hisal
代码如下
解法1 select e.name, s.grade from emp e,salgrade s where e.salary>=s.losal and e.salary<=s.hisal;
解法2 select e.name, s.grade from emp e,salgrade s where e.salary between s.losal and s.hisal;
5 查询策划部的所有员工的信息及工资等级
思路:本题,涉及三张表分别是 emp (员工信息表) ,salgrade (薪资等级表) ,dept(部门信息表)
emp(员工信息表)和dept(部门表)的连接条件:emp.dept_id=dept.id
emp和salgrade (薪资等级表)连接条件:emp.salary >=salgrade .losal emp.salary <=salgrade.hisal。同时我们要通过emp 表和 dept 表 ,得到策划部的员工信息,作为一张新的表。
代码如下
解法1
select e1.*, s.grade from (select e.* from emp e ,dept d where e.dept_id=d.id and d.name='策划部') e1,salgrade s where e1.salary>=s.losal and e1.salary<=s.hisal;解法2
代码如下
select e.*,s.grade from emp e ,dept d ,salgrade s where e.dept_id=d.id and( e.salary between s.losal and s.hisal )and d.name='策划部';
6 查询企划部 员工的平均工资
思路:本题 关联 emp表和dept表,通过内连接和外连接度可以。
内连接用法-隐式内连接
代码如下
select d.name, avg(e.salary) from emp e,dept d where e.dept_id=d.id and d.name='企划部';外连接用法-左外连接
代码如下
select d.name, avg(e.salary) from emp e left join dept d on e.dept_id=d.id where d.name='企划部';
7 查询工资比 刘敏高的员工信息
思路:本题 只涉及 emp表(员工信息表)
标量子查询
a 先求的员工刘敏的工资
代码如下:select e.salary from emp e where e.name='刘敏';
b 把求得刘敏工资作为条件,最终得到 比刘敏工资高的 员工信息
代码如下:select *from emp where salary>(select e.salary from emp e where e.name='刘敏');
8 查询比平均薪资高的员工信息
思路 :本题涉及emp表,标量子查询
标量子查询
a 查询平均薪资
代码如下:select avg(salary ) from emp ;
b 查询比平均薪资高的员工信息
代码如下:select *from emp where salary>(select avg(salary ) from emp );
9 查询低于本部门的平均工资的员工信息
错误思路,发现最后结果不对。因此仅供参考,
思路 本题涉及 emp 表 和dept表 连接条件: emp.dept_id=dept.id 同时 由于题目中,并没有指定具体是哪个部门,我们不妨先假设是企划部
a 查询本部门的平均薪资,我假定是 企划部
代码如下:
select avg(e.salary) from emp e,dept d where e.dept_id=d.id and d.name='企划部';b 查询低于本部门的平均工资的员工信息
先假设是 低于企划部的员工信息 ,代码如下:
select *from emp where salary< (select avg(e.salary) from emp e,dept d where e.dept_id=d.id and d.name='企划部');通过代码可以发现,通过改变指定 部门就可以,所以这里使用了列子查询。
代码如下
select e1.*,((select avg(e.salary) from emp e,dept d where e.dept_id=d.id and (d.name in(select dept.name from dept )))) '该部门平均薪资' from emp e1 where salary< (select avg(e.salary) from emp e,dept d where e.dept_id=d.id and (d.name any(select dept.name from dept ))); 运行报错
正确解法
我同样是假设部门id=1 求平均薪资
代码如下:select avg(e1.salary) from emp e1 where e1.dept_id=1;
可以是dept_id =1 也可以是2 等等
select avg(e1.salary) from emp e1 where e1.dept_id=2;
从这可以看出 在emp表中 当你要得到 id=1 所属部门的平均薪资,你要将id=1 那一行的dept_id 的值传进去,才行。因此代码如下
select e2.*,((select avg(e1.salary) from emp e1 where e1.dept_id=e2.dept_id)) '平均薪资' from emp e2 where e2.salary<(select avg(e1.salary) from emp e1 where e1.dept_id=e2.dept_id);
10 查询所有部门的信息,并统计部门的员工人数
思路:本题中有emp表和dept ,其中emp表是作为子查询参与,并充当外层SQL语句的字段使用的
代码如下:select * ,(select count(* )from emp where dept_id=dept.id ) '人数' from dept ;