MySQL 之复合查询(多表查询、子查询、合并查询)

复合查询使用数据库的scott样例数据库(简单的公司管理系统)来进行,该数据库中包含三张表,分别为:EMP(职员表),DEPT(部门表),SALGRADE(工资表);

多表查询

  • 显示雇员名、雇员工资以及所在部门的名字
    要查询的数据来自EMP和DEPT表,因此要联合查询:
    MySQL 之复合查询(多表查询、子查询、合并查询)_第1张图片
  • 显示部门号为10的部门名,员工名和工资:
    MySQL 之复合查询(多表查询、子查询、合并查询)_第2张图片
  • 显示各个员工的姓名,工资,及工资级别
mysql> select ename, sal, grade from EMP, SALGRADE where EMP.sal between losal and hisal;
+--------+---------+-------+
| ename  | sal     | grade |
+--------+---------+-------+
| SMITH  |  800.00 |     1 |
| ALLEN  | 1600.00 |     3 |
| WARD   | 1250.00 |     2 |
| JONES  | 2975.00 |     4 |
| MARTIN | 1250.00 |     2 |
| BLAKE  | 2850.00 |     4 |
| CLARK  | 2450.00 |     4 |
| SCOTT  | 3000.00 |     4 |
| KING   | 5000.00 |     5 |
| TURNER | 1500.00 |     3 |
| ADAMS  | 1100.00 |     1 |
| JAMES  |  950.00 |     1 |
| FORD   | 3000.00 |     4 |
| MILLER | 1300.00 |     2 |
+--------+---------+-------+
14 rows in set (0.02 sec)

子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询;

1. 单行子查询
显示与SMITH同一部门的员工:

mysql> select * from EMP WHERE deptno = (select deptno from EMP where ename='smith');
+--------+-------+---------+------+---------------------+---------+------+--------+
| empno  | ename | job     | mgr  | hiredate            | sal     | comm | deptno |
+--------+-------+---------+------+---------------------+---------+------+--------+
| 007369 | SMITH | CLERK   | 7902 | 1980-12-17 00:00:00 |  800.00 | NULL |     20 |
| 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
| 007788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL |     20 |
| 007876 | ADAMS | CLERK   | 7788 | 1987-05-23 00:00:00 | 1100.00 | NULL |     20 |
| 007902 | FORD  | ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL |     20 |
+--------+-------+---------+------+---------------------+---------+------+--------+
5 rows in set (0.01 sec)

2.多行子查询

多行子查询即为返回多行记录的子查询

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


mysql> select ename,job,sal,empno from emp where job in 
(select distinct job from emp where deptno=10) and deptno<>10;
+-------+---------+---------+--------+
| ename | job     | sal     | empno  |
+-------+---------+---------+--------+
| JONES | MANAGER | 2975.00 | 007566 |
| BLAKE | MANAGER | 2850.00 | 007698 |
| SMITH | CLERK   |  800.00 | 007369 |
| ADAMS | CLERK   | 1100.00 | 007876 |
| JAMES | CLERK   |  950.00 | 007900 |
+-------+---------+---------+--------+
5 rows in set (0.01 sec)

all关键字:显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号:

mysql> select ename, sal, deptno from EMP where sal > all(select sal from EMP where deptno=30);
+-------+---------+--------+
| ename | sal     | deptno |
+-------+---------+--------+
| JONES | 2975.00 |     20 |
| SCOTT | 3000.00 |     20 |
| KING  | 5000.00 |     10 |
| FORD  | 3000.00 |     20 |
+-------+---------+--------+
4 rows in set (0.01 sec)

any关键字:显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号:

mysql> select ename, sal, deptno from EMP where sal > any(select sal from EMP where deptno=30);
+--------+---------+--------+
| ename  | sal     | deptno |
+--------+---------+--------+
| ALLEN  | 1600.00 |     30 |
| WARD   | 1250.00 |     30 |
| JONES  | 2975.00 |     20 |
| MARTIN | 1250.00 |     30 |
| BLAKE  | 2850.00 |     30 |
| CLARK  | 2450.00 |     10 |
| SCOTT  | 3000.00 |     20 |
| KING   | 5000.00 |     10 |
| TURNER | 1500.00 |     30 |
| ADAMS  | 1100.00 |     20 |
| FORD   | 3000.00 |     20 |
| MILLER | 1300.00 |     10 |
+--------+---------+--------+
12 rows in set (0.01 sec)
  1. 在from子句中使用子查询
    子查询出现在from子句中,这种情况下将子查询当做一个临时表使用。

eg:

  • 显示高于自己部门平均工资的员工的姓名、部门、工资、平均工资:
mysql> select ename, deptno, sal, format(asal,2) from EMP,  
(select avg(sal) asal, deptno dt from EMP group by deptno) tmp where
 EMP.sal > tmp.asal and EMP.deptno=tmp.dt;
+-------+--------+---------+----------------+
| ename | deptno | sal     | format(asal,2) |
+-------+--------+---------+----------------+
| KING  |     10 | 5000.00 | 2,916.67       |
| JONES |     20 | 2975.00 | 2,175.00       |
| SCOTT |     20 | 3000.00 | 2,175.00       |
| FORD  |     20 | 3000.00 | 2,175.00       |
| ALLEN |     30 | 1600.00 | 1,566.67       |
| BLAKE |     30 | 2850.00 | 1,566.67       |
+-------+--------+---------+----------------+
6 rows in set (0.09 sec)
  • 查找每个部门工资最高的人的姓名、工资、部门、最高工资
mysql> 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;
+-------+---------+--------+---------+
| ename | sal     | deptno | ms      |
+-------+---------+--------+---------+
| BLAKE | 2850.00 |     30 | 2850.00 |
| SCOTT | 3000.00 |     20 | 3000.00 |
| KING  | 5000.00 |     10 | 5000.00 |
| FORD  | 3000.00 |     20 | 3000.00 |
+-------+---------+--------+---------+
4 rows in set (0.01 sec)
  • 显示每个部门的信息(部门名,编号,地址)和人员数量
mysql> select DEPT.dname, DEPT.deptno, DEPT.loc,count(*) '部门人数' from EMP,
 DEPT where EMP.deptno=DEPT.deptno group by DEPT.deptno,DEPT.dname,DEPT.loc;
+------------+--------+----------+--------------+
| dname      | deptno | loc      | 部门人数     |
+------------+--------+----------+--------------+
| ACCOUNTING |     10 | NEW YORK |            3 |
| RESEARCH   |     20 | DALLAS   |            5 |
| SALES      |     30 | CHICAGO  |            6 |
+------------+--------+----------+--------------+
3 rows in set (0.02 sec)

合并查询

在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all

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

eg:将工资大于2500或职位是MANAGER的人找出来

mysql> select ename,sal,job from EMP where sal > 2500 union
 select ename,sal,job from EMP where job = 'MANAGER';
+-------+---------+-----------+
| ename | sal     | job       |
+-------+---------+-----------+
| JONES | 2975.00 | MANAGER   |
| BLAKE | 2850.00 | MANAGER   |
| SCOTT | 3000.00 | ANALYST   |
| KING  | 5000.00 | PRESIDENT |
| FORD  | 3000.00 | ANALYST   |
| CLARK | 2450.00 | MANAGER   |
+-------+---------+-----------+
6 rows in set (0.00 sec)

2. union all

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

eg:将工资大于25000或职位是MANAGER的人找出来:

mysql> select ename,sal,job from EMP where sal > 2500 union all select ename,sal,job from EMP where job = 'MANAGER';
+-------+---------+-----------+
| ename | sal     | job       |
+-------+---------+-----------+
| JONES | 2975.00 | MANAGER   |
| BLAKE | 2850.00 | MANAGER   |
| SCOTT | 3000.00 | ANALYST   |
| KING  | 5000.00 | PRESIDENT |
| FORD  | 3000.00 | ANALYST   |
| JONES | 2975.00 | MANAGER   |
| BLAKE | 2850.00 | MANAGER   |
| CLARK | 2450.00 | MANAGER   |
+-------+---------+-----------+
8 rows in set (0.00 sec)

你可能感兴趣的:(MySQL 之复合查询(多表查询、子查询、合并查询))