Mysql---复合查询(多表连接、自连接、子查询(any all) from子句查询、union)

本篇博客对表的操作基于以下几个表:

首先了解下简单查询即对一个表的查询:
1.员工信息表emp

mysql> select * from emp;

在这里插入图片描述
2.公司部门信息表dept(部门号、部门名称、位置)

mysql> select * from dept;

在这里插入图片描述
3.工资等级表salgrade(工资等级、当地工资、最高工资)
在这里插入图片描述

首先看几个简单查询:
1.显示每个部门的平均工资和最高工资

mysql> select deptno,avg(sal),max(sal) from emp group by deptno;

在这里插入图片描述
2.显示平均工资低于2000的部门号和它的平均工资

mysql> select deptno,avg(sal) from emp group by deptno having avg(sal)<2000;

在这里插入图片描述
3.显示每种岗位的雇员总数,平均工资

mysql> select job,count(*),avg(sal) from emp group by job;

在这里插入图片描述

接下来了解复合查询:
多表连接
1.显示雇员名、雇员工资以及所在部门的名字
因为要查询的数据来自两个表(emp和dept),这时就要把2个表利用相同属性连接一起,可以发现2个表的相同属性是deptno。

mysql> select ename,sal,dname from emp,dept where emp.deptno=dept.deptno;

在这里插入图片描述
2.显示部门号为10的部门名,员工名和工资

mysql> select dname,ename,sal from emp,dept where dept.deptno=10 and dept.deptno=emp.deptno;

在这里插入图片描述
3.显示各个员工的姓名,工资,及工资级别
emp表和salgrade 2张表根据工资连接一起,找出员工工资符合salgrade 表的区间,即是工资等级。

mysql> select ename,sal,grade from emp,salgrade where sal between losal and hisal;

在这里插入图片描述

自连接
自连接指同一张表连接查询。

1.显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号–empno)
方法1:使用子查询
找出FORD领导的编号,根据这个编号查询:

mysql> select empno,ename from emp where empno=(select mgr from emp where ename='FORD');

方法2:自查询:leader表和worker表。leader表的员工编号等于worker表的FORD的领导编号。

mysql> select leader.empno,leader.ename from emp as leader,emp as worker where worker.ename='FORD' and leader.empno=worker.mgr;

在这里插入图片描述
子查询
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。
单行子查询:
例:显示SMITH同一部门的员工

mysql> select * from emp where deptno=(select deptno from emp where ename='SMITH');

在这里插入图片描述

多行子查询:
1.使用in关键字
查询和10号部门的工作相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的

mysql> select ename,job,sal,deptno from emp where job in(select job  from emp where deptno=10) and deptno<>10;

在这里插入图片描述
2.使用all关键字
显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号
方法1:使用all关键字

mysql> select ename,sal,deptno from emp where sal>all(select sal from emp where deptno=30);

在这里插入图片描述
方法2:max函数

mysql> select ename, sal, deptno from emp where sal > (select max(sal) from emp where deptno=30);

在这里插入图片描述
3.使用any关键字;
显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号
方法1:使用any

mysql> select ename,sal,deptno from emp where sal > any(select sal from emp where deptno=30);

方法2:min函数

mysql> select ename,sal,deptno from emp where sal > (select min(sal) from emp where deptno=30);

在这里插入图片描述
多列子查询:
单行子查询是指子查询只返回单列,单行数据;多行子查询是指返回单列多行数据,都是针对单列而言的,而多列
子查询则是指查询返回多个列数据的子查询语句

例:查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人

mysql> select ename,deptno,job from emp where (deptno,job)=(select deptno ,job from emp where ename='SMITH') and ename<>'SMITH';

在这里插入图片描述
在from子句中使用子查询
把子查询当做临时表使用。
1.显示高于自己部门平均工资的员工的姓名、部门、工资、平均工资

先把每个部门的平均工资生成一个临时表tmp,再从emp和tmp表中查询:

mysql> select ename,emp.deptno,sal,savg from emp,(select deptno ,avg(sal) as savg from emp group by deptno) as tmp
    -> where (emp.deptno=tmp.deptno) and (emp.sal> tmp.savg);

在这里插入图片描述

2.查找每个部门工资最高的人的姓名、工资、部门、最高工资

先将每个部门的最高工资生成一个临时表tmp,再从emp和tmp中匹配同一部门的最高工资。

mysql> select emp.ename,sal,emp.deptno,smax from emp,(select max(sal) as smax ,deptno from emp group by deptno) tmp
    -> where emp.deptno=tmp.deptno and sal=smax;

在这里插入图片描述

3.显示每个部门的信息(部门名,编号,地址)和人员数量
方法1:先找到每个部门的人员数量生成临时表tmp,dept表和tmp连接:

mysql> select dname,dept.deptno,loc,empnum from dept,(select deptno,count(*) as empnum from emp group by deptno ) tmp
    -> where tmp.deptno=dept.deptno;

在这里插入图片描述
方法2:

mysql> select dept.deptno,dept.dname,dept.loc,count(*) from dept,emp where dept.deptno=emp.deptno group by dept.deptno;

在这里插入图片描述
可以在where子句中用连接:
例:获取所有非manager的员工emp_no

CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

方法1:

select emp_no from employees where
emp_no not in(select emp_no from dept_manager);

方法2:连接通常可以在select语句的from子句或where子句中建立。
left join(左连接)是以A表的记录为基础的,A可以看成左表,B可以看成右表,
left join是以左表为准的。
换句话说,左表(A)的记录将会全部表示出来,
而右表(B)只会显示符合搜索条件的记录。
B表记录不足的地方均为NULL。
如:select * from A left join B on A.ID = B.ID

select emp_no from (select * from dept_manager,employees where 
                   dept_manager.emp_no=employees.emp_no) tmp
where tmp.dept_no IS NULL;

合并查询:
将多个select执行结果进行合并,可以用union和union all。
union:取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。
例:将工资大于2500或职位是MANAGER的人找出来
方法1:(or)

mysql> select ename,sal,job from emp where sal>2500 or job='manager';

在这里插入图片描述
方法2:union:

mysql> select ename,sal,job from emp where sal>2500 union
    -> select ename,sal,job from emp where job='manager';

union all
该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。

mysql> select ename,sal,job from emp where sal>2500 union all
    -> select ename,sal,job from emp where job='manager';

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/sophia__yu/article/details/85059744