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