文章目录
- 一、基本查询
- 1.1 查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为J
- 1.2 按照部门号升序且员工工资降序进行排序
- 1.3 使用年薪(月薪*12+奖金)进行降序排序
- 二、简单子查询
- 2.1 查找最高工资员工及其所在的部门
- 2.2 显示高于平均工资的员工信息
- 三、聚合查询
- 3.1 显示每个部门的平均工资和最高工资
- 3.2 显示平均工资低于2000的部门号和它的平均工资
- 3.3 显示每种岗位的雇员总数及其平均工资
- 四、多表查询
- 4.1 显示员工名、员工工资及其所在的部门名字
- 4.2 显示部门号为10的部门名,员工名和工资
- 4.3 显示各个员工的姓名,工资,及工资级别
- 五、自连接
- 六、复杂自查询
- 6.1 在where子句子查询(条件判断)
- 6.1.1 单行子查询
- 6.1.2多行子查询
- 6.1.3 多列子查询
- 6.2 在from子句中使用子查询
- 6.2.1 显示每个高于自己部门平均工资的员工的姓名、部门
- 6.2.2 显示每个高于自己部门平均工资的员工的姓名、部门、部门地点
- 3.2.3 查找每个部门工资最高的人的姓名、工资、部门、最高工资
- 3.2.4 显示每个部门的信息(部门名,编号,地址)和人员数量
- 七、合并查询
- 7.1 union(并集+去重)
- 7.2 union all(并集+不去重)
一、基本查询
mysql> select * from emp;+--------+--------+-----------+------+---------------------+---------+---------+--------+| empno| ename| job | mgr| hiredate| sal | comm| deptno |+--------+--------+-----------+------+---------------------+---------+---------+--------+| 007369 | SMITH| CLERK | 7902 | 1980-12-17 00:00:00 |800.00 |NULL | 20 || 007499 | ALLEN| SALESMAN| 7698 | 1981-02-20 00:00:00 | 1600.00 |300.00 | 30 || 007521 | WARD | SALESMAN| 7698 | 1981-02-22 00:00:00 | 1250.00 |500.00 | 30 || 007566 | JONES| MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 |NULL | 20 || 007654 | MARTIN | SALESMAN| 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 | 30 || 007698 | BLAKE| MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 |NULL | 30 || 007782 | CLARK| MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 |NULL | 10 || 007788 | SCOTT| ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 |NULL | 20 || 007839 | KING | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |NULL | 10 || 007844 | TURNER | SALESMAN| 7698 | 1981-09-08 00:00:00 | 1500.00 |0.00 | 30 || 007876 | ADAMS| CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 |NULL | 20 || 007900 | JAMES| CLERK | 7698 | 1981-12-03 00:00:00 |950.00 |NULL | 30 || 007902 | FORD | ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 |NULL | 20 || 007934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00 | 1300.00 |NULL | 10 |+--------+--------+-----------+------+---------------------+---------+---------+--------+14 rows in set (0.00 sec)
1.1 查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为J
mysql> select * from emp where (sal>500 or job='MANAGER') and ename like 'J%';+--------+-------+---------+------+---------------------+---------+------+--------+| empno| ename | job | mgr| hiredate| sal | comm | deptno |+--------+-------+---------+------+---------------------+---------+------+--------+| 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL | 20 || 007900 | JAMES | CLERK | 7698 | 1981-12-03 00:00:00 |950.00 | NULL | 30 |+--------+-------+---------+------+---------------------+---------+------+--------+2 rows in set (0.00 sec)mysql> select * from emp where (sal > 500 or job='MANAGER') and substring(ename, 1, 1)='J';+--------+-------+---------+------+---------------------+---------+------+--------+| empno| ename | job | mgr| hiredate| sal | comm | deptno |+--------+-------+---------+------+---------------------+---------+------+--------+| 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL | 20 || 007900 | JAMES | CLERK | 7698 | 1981-12-03 00:00:00 |950.00 | NULL | 30 |+--------+-------+---------+------+---------------------+---------+------+--------+2 rows in set (0.00 sec)
1.2 按照部门号升序且员工工资降序进行排序
mysql> select * from emp order by empno ASC, sal DESC;+--------+--------+-----------+------+---------------------+---------+---------+--------+| empno| ename| job | mgr| hiredate| sal | comm| deptno |+--------+--------+-----------+------+---------------------+---------+---------+--------+| 007369 | SMITH| CLERK | 7902 | 1980-12-17 00:00:00 |800.00 |NULL | 20 || 007499 | ALLEN| SALESMAN| 7698 | 1981-02-20 00:00:00 | 1600.00 |300.00 | 30 || 007521 | WARD | SALESMAN| 7698 | 1981-02-22 00:00:00 | 1250.00 |500.00 | 30 || 007566 | JONES| MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 |NULL | 20 || 007654 | MARTIN | SALESMAN| 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 | 30 || 007698 | BLAKE| MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 |NULL | 30 || 007782 | CLARK| MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 |NULL | 10 || 007788 | SCOTT| ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 |NULL | 20 || 007839 | KING | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |NULL | 10 || 007844 | TURNER | SALESMAN| 7698 | 1981-09-08 00:00:00 | 1500.00 |0.00 | 30 || 007876 | ADAMS| CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 |NULL | 20 || 007900 | JAMES| CLERK | 7698 | 1981-12-03 00:00:00 |950.00 |NULL | 30 || 007902 | FORD | ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 |NULL | 20 || 007934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00 | 1300.00 |NULL | 10 |+--------+--------+-----------+------+---------------------+---------+---------+--------+14 rows in set (0.00 sec)mysql> select ename, empno, sal from emp order by empno, sal DESC;+--------+--------+---------+| ename| empno| sal |+--------+--------+---------+| SMITH| 007369 |800.00 || ALLEN| 007499 | 1600.00 || WARD | 007521 | 1250.00 || JONES| 007566 | 2975.00 || MARTIN | 007654 | 1250.00 || BLAKE| 007698 | 2850.00 || CLARK| 007782 | 2450.00 || SCOTT| 007788 | 3000.00 || KING | 007839 | 5000.00 || TURNER | 007844 | 1500.00 || ADAMS| 007876 | 1100.00 || JAMES| 007900 |950.00 || FORD | 007902 | 3000.00 || MILLER | 007934 | 1300.00 |+--------+--------+---------+14 rows in set (0.00 sec)
1.3 使用年薪(月薪*12+奖金)进行降序排序
mysql> select ename, sal, commfrom emp order by (sal*12 + ifnull(comm, 0)) DESC;+--------+---------+---------+| ename| sal | comm|+--------+---------+---------+| KING | 5000.00 |NULL || SCOTT| 3000.00 |NULL || FORD | 3000.00 |NULL || JONES| 2975.00 |NULL || BLAKE| 2850.00 |NULL || CLARK| 2450.00 |NULL || ALLEN| 1600.00 |300.00 || TURNER | 1500.00 |0.00 || MARTIN | 1250.00 | 1400.00 || MILLER | 1300.00 |NULL || WARD | 1250.00 |500.00 || ADAMS| 1100.00 |NULL || JAMES|950.00 |NULL || SMITH|800.00 |NULL |+--------+---------+---------+14 rows in set (0.00 sec)# 把年薪显示出来mysql> select ename, sal, comm, (sal * 12 + ifnull(comm, 0)) as 年薪 from emp order by 年薪DESC;+--------+---------+---------+----------+| ename| sal | comm| 年薪 |+--------+---------+---------+----------+| KING | 5000.00 |NULL | 60000.00 || SCOTT| 3000.00 |NULL | 36000.00 || FORD | 3000.00 |NULL | 36000.00 || JONES| 2975.00 |NULL | 35700.00 || BLAKE| 2850.00 |NULL | 34200.00 || CLARK| 2450.00 |NULL | 29400.00 || ALLEN| 1600.00 |300.00 | 19500.00 || TURNER | 1500.00 |0.00 | 18000.00 || MARTIN | 1250.00 | 1400.00 | 16400.00 || MILLER | 1300.00 |NULL | 15600.00 || WARD | 1250.00 |500.00 | 15500.00 || ADAMS| 1100.00 |NULL | 13200.00 || JAMES|950.00 |NULL | 11400.00 || SMITH|800.00 |NULL |9600.00 |+--------+---------+---------+----------+14 rows in set (0.00 sec)
二、简单子查询
2.1 查找最高工资员工及其所在的部门
可以在SQL语句内部进行子查询,先执行内部SQL,再执行外部SQL。
mysql> select ename, sal, job from emp where sal=(select max(sal) from emp);+-------+---------+-----------+| ename | sal | job |+-------+---------+-----------+| KING| 5000.00 | PRESIDENT |+-------+---------+-----------+1 row in set (0.00 sec)
2.2 显示高于平均工资的员工信息
mysql> select * from emp where sal>(select avg(sal) from emp);+--------+-------+-----------+------+---------------------+---------+------+--------+| empno| ename | job | mgr| hiredate| sal | comm | deptno |+--------+-------+-----------+------+---------------------+---------+------+--------+| 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL | 20 || 007698 | BLAKE | MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 | NULL | 30 || 007782 | CLARK | MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 | NULL | 10 || 007788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL | 20 || 007839 | KING| PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL | 10 || 007902 | FORD| ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL | 20 |+--------+-------+-----------+------+---------------------+---------+------+--------+6 rows in set (0.00 sec)
三、聚合查询
3.1 显示每个部门的平均工资和最高工资
mysql> select deptno, avg(sal) 平均, max(sal) 最高 from emp group by deptno;+--------+-------------+---------+| deptno | 平均| 最高|+--------+-------------+---------+| 10 | 2916.666667 | 5000.00 || 20 | 2175.000000 | 3000.00 || 30 | 1566.666667 | 2850.00 |+--------+-------------+---------+3 rows in set (0.00 sec)# 为了美观可以保留精度mysql> select deptno, format(avg(sal),2) 平均, format(max(sal), 2) 最高 from emp group by depptno;+--------+----------+----------+| deptno | 平均 | 最高 |+--------+----------+----------+| 10 | 2,916.67 | 5,000.00 || 20 | 2,175.00 | 3,000.00 || 30 | 1,566.67 | 2,850.00 |+--------+----------+----------+3 rows in set (0.00 sec)
3.2 显示平均工资低于2000的部门号和它的平均工资
mysql> select deptno, avg(sal) 平均工资 from emp group by deptno having avg(sal)<2000;+--------+--------------+| deptno | 平均工资 |+--------+--------------+| 30 |1566.666667 |+--------+--------------+1 row in set (0.00 sec)
3.3 显示每种岗位的雇员总数及其平均工资
mysql> select job, count(ename) 雇员总数, avg(sal) 平均工资 from emp group by job;+-----------+--------------+--------------+| job | 雇员总数 | 平均工资 |+-----------+--------------+--------------+| ANALYST |2 |3000.000000 || CLERK |4 |1037.500000 || MANAGER |3 |2758.333333 || PRESIDENT |1 |5000.000000 || SALESMAN|4 |1400.000000 |+-----------+--------------+--------------+5 rows in set (0.00 sec)
四、多表查询
实际上很多时候我们要查的数据可能不在同一张表,所以需要多表查询。
比方说一张表里面有2行信息,另一个表里面有3行信息,如果直接select * form 表1,表2
那么就会在表中进行穷举组合(得到的结果称为笛卡尔积),生成6行信息。
可以看到SMITH这个人明明是20号部门的,但是也还是会拼接上其他部门的无效信息。
使用笛卡尔积后,后面必定紧跟一个where子句来确定多张表共同的字段,筛掉多张表中排列组合出来的无效数据,仅留下有效数据供程序员排查。
这样,多表查询问题就转化成了单表查询。
mysql> select * from emp as e, dept as d where e.deptno=d.deptno;+--------+--------+-----------+------+---------------------+---------+---------+--------+--------+------------+----------+| empno| ename| job | mgr| hiredate| sal | comm| deptno | deptno | dname| loc|+--------+--------+-----------+------+---------------------+---------+---------+--------+--------+------------+----------+| 007369 | SMITH| CLERK | 7902 | 1980-12-17 00:00:00 |800.00 |NULL | 20 | 20 | RESEARCH | DALLAS || 007499 | ALLEN| SALESMAN| 7698 | 1981-02-20 00:00:00 | 1600.00 |300.00 | 30 | 30 | SALES| CHICAGO|| 007521 | WARD | SALESMAN| 7698 | 1981-02-22 00:00:00 | 1250.00 |500.00 | 30 | 30 | SALES| CHICAGO|| 007566 | JONES| MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 |NULL | 20 | 20 | RESEARCH | DALLAS || 007654 | MARTIN | SALESMAN| 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 | 30 | 30 | SALES| CHICAGO|| 007698 | BLAKE| MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 |NULL | 30 | 30 | SALES| CHICAGO|| 007782 | CLARK| MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 |NULL | 10 | 10 | ACCOUNTING | NEW YORK || 007788 | SCOTT| ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 |NULL | 20 | 20 | RESEARCH | DALLAS || 007839 | KING | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |NULL | 10 | 10 | ACCOUNTING | NEW YORK || 007844 | TURNER | SALESMAN| 7698 | 1981-09-08 00:00:00 | 1500.00 |0.00 | 30 | 30 | SALES| CHICAGO|| 007876 | ADAMS| CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 |NULL | 20 | 20 | RESEARCH | DALLAS || 007900 | JAMES| CLERK | 7698 | 1981-12-03 00:00:00 |950.00 |NULL | 30 | 30 | SALES| CHICAGO|| 007902 | FORD | ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 |NULL | 20 | 20 | RESEARCH | DALLAS || 007934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00 | 1300.00 |NULL | 10 | 10 | ACCOUNTING | NEW YORK |+--------+--------+-----------+------+---------------------+---------+---------+--------+--------+------------+----------+14 rows in set (0.00 sec)
4.1 显示员工名、员工工资及其所在的部门名字
mysql> select ename,sal,dname from emp as e, dept as d where e.deptno=d.deptno;+--------+---------+------------+| ename| sal | dname|+--------+---------+------------+| SMITH|800.00 | RESEARCH || ALLEN| 1600.00 | SALES|| WARD | 1250.00 | SALES|| JONES| 2975.00 | RESEARCH || MARTIN | 1250.00 | SALES|| BLAKE| 2850.00 | SALES|| CLARK| 2450.00 | ACCOUNTING || SCOTT| 3000.00 | RESEARCH || KING | 5000.00 | ACCOUNTING || TURNER | 1500.00 | SALES|| ADAMS| 1100.00 | RESEARCH || JAMES|950.00 | SALES|| FORD | 3000.00 | RESEARCH || MILLER | 1300.00 | ACCOUNTING |+--------+---------+------------+14 rows in set (0.00 sec)
4.2 显示部门号为10的部门名,员工名和工资
mysql> select e.deptno,dname,ename,sal from emp as e,dept as d where e.deptno=d.deptno and e.deptno=10;+--------+------------+--------+---------+| deptno | dname| ename| sal |+--------+------------+--------+---------+| 10 | ACCOUNTING | CLARK| 2450.00 || 10 | ACCOUNTING | KING | 5000.00 || 10 | ACCOUNTING | MILLER | 1300.00 |+--------+------------+--------+---------+3 rows in set (0.00 sec)
4.3 显示各个员工的姓名,工资,及工资级别
mysql> select ename,sal,grade from emp,salgrade where sal>losal and sal<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 || KING | 5000.00 | 5 || TURNER | 1500.00 | 3 || ADAMS| 1100.00 | 1 || JAMES|950.00 | 1 || MILLER | 1300.00 | 2 |+--------+---------+-------+12 rows in set (0.00 sec)
五、自连接
刚刚我们多表连接的时候使用两张表做笛卡尔积,那如果想对同一张表做笛卡尔积呢?
mysql> select * from salgrade s1, salgrade s2;+-------+-------+-------+-------+-------+-------+| grade | losal | hisal | grade | losal | hisal |+-------+-------+-------+-------+-------+-------+| 1 | 700 |1200 | 1 | 700 |1200 || 2 |1201 |1400 | 1 | 700 |1200 || 3 |1401 |2000 | 1 | 700 |1200 || 4 |2001 |3000 | 1 | 700 |1200 || 5 |3001 |9999 | 1 | 700 |1200 || 1 | 700 |1200 | 2 |1201 |1400 || 2 |1201 |1400 | 2 |1201 |1400 || 3 |1401 |2000 | 2 |1201 |1400 || 4 |2001 |3000 | 2 |1201 |1400 || 5 |3001 |9999 | 2 |1201 |1400 || 1 | 700 |1200 | 3 |1401 |2000 || 2 |1201 |1400 | 3 |1401 |2000 || 3 |1401 |2000 | 3 |1401 |2000 || 4 |2001 |3000 | 3 |1401 |2000 || 5 |3001 |9999 | 3 |1401 |2000 || 1 | 700 |1200 | 4 |2001 |3000 || 2 |1201 |1400 | 4 |2001 |3000 || 3 |1401 |2000 | 4 |2001 |3000 || 4 |2001 |3000 | 4 |2001 |3000 || 5 |3001 |9999 | 4 |2001 |3000 || 1 | 700 |1200 | 5 |3001 |9999 || 2 |1201 |1400 | 5 |3001 |9999 || 3 |1401 |2000 | 5 |3001 |9999 || 4 |2001 |3000 | 5 |3001 |9999 || 5 |3001 |9999 | 5 |3001 |9999 |+-------+-------+-------+-------+-------+-------+25 rows in set (0.00 sec)
自连接是指在同一张表连接查询。
对同一张表做重命名,在同一张表连接查询
- 显示员工FORD的上级领导的编号(mgr)和姓名
首先找到FORD领导的编号,然后再利用编号自查寻领导的姓名
# 子查询mysql> select ename from emp where empno=(select mgr from emp where ename = 'FORD');+-------+| ename |+-------+| JONES |+-------+1 row in set (0.00 sec)# 自连接mysql> select e2.ename from emp as e1, emp as e2 where e1.ename='FORD' and e1.mgr=e2.empno;+-------+| ename |+-------+| JONES |+-------+1 row in set (0.00 sec)
六、复杂自查询
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。
子查询在where子句中使用,充当判断条件,在from子句中出现,充当笛卡尔积。
6.1 在where子句子查询(条件判断)
6.1.1 单行子查询
显示SMITH同一部门的员工
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.00 sec)
6.1.2多行子查询
- 查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的
in关键字: 用来判断一个列值是否在集合当中。
mysql> select distinct ename,job,sal,deptno from emp where job in (select distinct job from emp where deptno=10) and deptno!=10;+-------+---------+---------+--------+| ename | job | sal | deptno |+-------+---------+---------+--------+| JONES | MANAGER | 2975.00 | 20 || BLAKE | MANAGER | 2850.00 | 30 || SMITH | CLERK |800.00 | 20 || ADAMS | CLERK | 1100.00 | 20 || JAMES | CLERK |950.00 | 30 |+-------+---------+---------+--------+5 rows in set (0.00 sec)
- 显示工资比部门30的所有员工的工资高的员工信息
all: >all()就表示比括号里面的所有数据都大
思路是先找到部门30的最高工资,再查找比他高的。
mysql> select * from emp where sal > (select max(sal) from emp where deptno=30);+--------+-------+-----------+------+---------------------+---------+------+--------+| empno| ename | job | mgr| hiredate| sal | comm | deptno |+--------+-------+-----------+------+---------------------+---------+------+--------+| 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 || 007839 | KING| PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL | 10 || 007902 | FORD| ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL | 20 |+--------+-------+-----------+------+---------------------+---------+------+--------+4 rows in set (0.00 sec)mysql> select * from emp where sal > all(select sal from emp where deptno=30);+--------+-------+-----------+------+---------------------+---------+------+--------+| empno| ename | job | mgr| hiredate| sal | comm | deptno |+--------+-------+-----------+------+---------------------+---------+------+--------+| 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 || 007839 | KING| PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL | 10 || 007902 | FORD| ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL | 20 |+--------+-------+-----------+------+---------------------+---------+------+--------+4 rows in set (0.00 sec)
- 显示工资比部门30的任意(最低)员工的工资高的员工信息
any: 表示任意
mysql> select * from emp where sal > any(select distinct sal from emp where deptno=30);+--------+--------+-----------+------+---------------------+---------+---------+--------+| empno| ename| job | mgr| hiredate| sal | comm| deptno |+--------+--------+-----------+------+---------------------+---------+---------+--------+| 007499 | ALLEN| SALESMAN| 7698 | 1981-02-20 00:00:00 | 1600.00 |300.00 | 30 || 007521 | WARD | SALESMAN| 7698 | 1981-02-22 00:00:00 | 1250.00 |500.00 | 30 || 007566 | JONES| MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 |NULL | 20 || 007654 | MARTIN | SALESMAN| 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 | 30 || 007698 | BLAKE| MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 |NULL | 30 || 007782 | CLARK| MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 |NULL | 10 || 007788 | SCOTT| ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 |NULL | 20 || 007839 | KING | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |NULL | 10 || 007844 | TURNER | SALESMAN| 7698 | 1981-09-08 00:00:00 | 1500.00 |0.00 | 30 || 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 || 007934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00 | 1300.00 |NULL | 10 |+--------+--------+-----------+------+---------------------+---------+---------+--------+12 rows in set (0.00 sec)
6.1.3 多列子查询
单行子查询是指子查询只返回单列,单行数据;多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询是指查询返回多个列数据的子查询语句。
- 查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人
mysql> select ename from emp where (deptno, job)=(select deptno, job from emp where ename='SMITHH') and ename!= 'SMITH';+-------+| ename |+-------+| ADAMS |+-------+1 row in set (0.00 sec)
6.2 在from子句中使用子查询
6.2.1 显示每个高于自己部门平均工资的员工的姓名、部门
# 先筛选出每个部门的平均工资mysql> select deptno, avg(sal) from emp group by deptno;+--------+-------------+| deptno | avg(sal)|+--------+-------------+| 10 | 2916.666667 || 20 | 2175.000000 || 30 | 1566.666667 |+--------+-------------+3 rows in set (0.00 sec)# 多表查询mysql> select * from emp, (select deptno, avg(sal) from emp group by deptno) tmp;………………# 转变成单表信息mysql> select * from emp, (select deptno, avg(sal) 平均工资 from emp group by deptno) 临时表 wheere +--------+--------+-----------+------+---------------------+---------+---------+--------+--------+-------------+| empno| ename| job | mgr| hiredate| sal | comm| deptno | deptno | avg(sal)|+--------+--------+-----------+------+---------------------+---------+---------+--------+--------+-------------+| 007369 | SMITH| CLERK | 7902 | 1980-12-17 00:00:00 |800.00 |NULL | 20 | 20 | 2175.000000 || 007499 | ALLEN| SALESMAN| 7698 | 1981-02-20 00:00:00 | 1600.00 |300.00 | 30 | 30 | 1566.666667 || 007521 | WARD | SALESMAN| 7698 | 1981-02-22 00:00:00 | 1250.00 |500.00 | 30 | 30 | 1566.666667 || 007566 | JONES| MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 |NULL | 20 | 20 | 2175.000000 || 007654 | MARTIN | SALESMAN| 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 | 30 | 30 | 1566.666667 || 007698 | BLAKE| MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 |NULL | 30 | 30 | 1566.666667 || 007782 | CLARK| MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 |NULL | 10 | 10 | 2916.666667 || 007788 | SCOTT| ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 |NULL | 20 | 20 | 2175.000000 || 007839 | KING | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |NULL | 10 | 10 | 2916.666667 || 007844 | TURNER | SALESMAN| 7698 | 1981-09-08 00:00:00 | 1500.00 |0.00 | 30 | 30 | 1566.666667 || 007876 | ADAMS| CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 |NULL | 20 | 20 | 2175.000000 || 007900 | JAMES| CLERK | 7698 | 1981-12-03 00:00:00 |950.00 |NULL | 30 | 30 | 1566.666667 || 007902 | FORD | ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 |NULL | 20 | 20 | 2175.000000 || 007934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00 | 1300.00 |NULL | 10 | 10 | 2916.666667 |+--------+--------+-----------+------+---------------------+---------+---------+--------+--------+-------------+14 rows in set (0.00 sec)# 单表查询mysql> select ename, emp.deptno from emp, (select deptno, avg(sal) 平均工资 from emp group by deeptno) 临时表 where emp.deptno=临时表.deptno and emp.sal > 平均工资;+-------+--------+| ename | deptno |+-------+--------+| ALLEN | 30 || JONES | 20 || BLAKE | 30 || SCOTT | 20 || KING| 10 || FORD| 20 |+-------+--------+6 rows in set (0.00 sec)
6.2.2 显示每个高于自己部门平均工资的员工的姓名、部门、部门地点
这一问比上一问多了一个部门地点,涉及到多表查询。
做笛卡尔积然后筛选有效信息
# 做笛卡尔积mysql> select * from dept, (select ename, emp.deptno from emp, (select deptno, avg(sal) 平均工资 from emp group by deptno) 临时表 where emp.deptno=临时表.deptno and emp.sal> 平均工资) t1;+--------+------------+----------+-------+--------+| deptno | dname| loc| ename | deptno |+--------+------------+----------+-------+--------+| 10 | ACCOUNTING | NEW YORK | ALLEN | 30 || 20 | RESEARCH | DALLAS | ALLEN | 30 || 30 | SALES| CHICAGO| ALLEN | 30 || 40 | OPERATIONS | BOSTON | ALLEN | 30 || 10 | ACCOUNTING | NEW YORK | JONES | 20 || 20 | RESEARCH | DALLAS | JONES | 20 || 30 | SALES| CHICAGO| JONES | 20 || 40 | OPERATIONS | BOSTON | JONES | 20 || 10 | ACCOUNTING | NEW YORK | BLAKE | 30 || 20 | RESEARCH | DALLAS | BLAKE | 30 || 30 | SALES| CHICAGO| BLAKE | 30 || 40 | OPERATIONS | BOSTON | BLAKE | 30 || 10 | ACCOUNTING | NEW YORK | SCOTT | 20 || 20 | RESEARCH | DALLAS | SCOTT | 20 || 30 | SALES| CHICAGO| SCOTT | 20 || 40 | OPERATIONS | BOSTON | SCOTT | 20 || 10 | ACCOUNTING | NEW YORK | KING| 10 || 20 | RESEARCH | DALLAS | KING| 10 || 30 | SALES| CHICAGO| KING| 10 || 40 | OPERATIONS | BOSTON | KING| 10 || 10 | ACCOUNTING | NEW YORK | FORD| 20 || 20 | RESEARCH | DALLAS | FORD| 20 || 30 | SALES| CHICAGO| FORD| 20 || 40 | OPERATIONS | BOSTON | FORD| 20 |+--------+------------+----------+-------+--------+24 rows in set (0.00 sec)# 筛选有效信息mysql> select t1.ename, dept.loc, t1.deptno from dept, (select ename, emp.deptno from emp, (select deptno, avg(sal) 平均工资 from emp group by deptno) 临时表 where emp.deptnoo=临时表.deptno and emp.sal > 平均工资) t1 where dept.deptno=t1.deptno;+-------+----------+--------+| ename | loc| deptno |+-------+----------+--------+| ALLEN | CHICAGO| 30 || JONES | DALLAS | 20 || BLAKE | CHICAGO| 30 || SCOTT | DALLAS | 20 || KING| NEW YORK | 10 || FORD| DALLAS | 20 |+-------+----------+--------+6 rows in set (0.01 sec)
3.2.3 查找每个部门工资最高的人的姓名、工资、部门、最高工资
# 通过group by聚合找出各部门的最高工资mysql> select deptno,max(sal) from emp group by deptno;+--------+----------+| deptno | max(sal) |+--------+----------+| 10 |5000.00 || 20 |3000.00 || 30 |2850.00 |+--------+----------+3 rows in set (0.00 sec)# 做笛卡尔积并筛选有效信息mysql> select * from emp, (select deptno,max(sal) from emp group by deptno) 部门最高工资 where emp.deptno=部门最高工资.deptno;+--------+--------+-----------+------+---------------------+---------+---------+--------+--------+----------+| empno| ename| job | mgr| hiredate| sal | comm| deptno | deptno | max(sal) |+--------+--------+-----------+------+---------------------+---------+---------+--------+--------+----------+| 007369 | SMITH| CLERK | 7902 | 1980-12-17 00:00:00 |800.00 |NULL | 20 | 20 |3000.00 || 007499 | ALLEN| SALESMAN| 7698 | 1981-02-20 00:00:00 | 1600.00 |300.00 | 30 | 30 |2850.00 || 007521 | WARD | SALESMAN| 7698 | 1981-02-22 00:00:00 | 1250.00 |500.00 | 30 | 30 |2850.00 || 007566 | JONES| MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 |NULL | 20 | 20 |3000.00 || 007654 | MARTIN | SALESMAN| 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 | 30 | 30 |2850.00 || 007698 | BLAKE| MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 |NULL | 30 | 30 |2850.00 || 007782 | CLARK| MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 |NULL | 10 | 10 |5000.00 || 007788 | SCOTT| ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 |NULL | 20 | 20 |3000.00 || 007839 | KING | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |NULL | 10 | 10 |5000.00 || 007844 | TURNER | SALESMAN| 7698 | 1981-09-08 00:00:00 | 1500.00 |0.00 | 30 | 30 |2850.00 || 007876 | ADAMS| CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 |NULL | 20 | 20 |3000.00 || 007900 | JAMES| CLERK | 7698 | 1981-12-03 00:00:00 |950.00 |NULL | 30 | 30 |2850.00 || 007902 | FORD | ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 |NULL | 20 | 20 |3000.00 || 007934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00 | 1300.00 |NULL | 10 | 10 |5000.00 |+--------+--------+-----------+------+---------------------+---------+---------+--------+--------+----------+14 rows in set (0.00 sec)# 在添加工资等于最高工资的条件mysql> select ename, sal, emp.deptno, maxsal from emp, (select deptno,max(sal) maxsal from emp group by deptno) 部门最高工资 where emp.deptno=部门最高工资.deptno and 部门.高工资.maxsal=emp.sal;+-------+---------+--------+---------+| ename | sal | deptno | maxsal|+-------+---------+--------+---------+| 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.00 sec)
3.2.4 显示每个部门的信息(部门名,编号,地址)和人员数量
- 多表方法
1️⃣ 先统计每个部门有多少人
mysql> select deptno, count(*) dep_num from emp group by deptno;+--------+---------+| deptno | dep_num |+--------+---------+| 10 | 3 || 20 | 5 || 30 | 6 |+--------+---------+3 rows in set (0.00 sec)
2️⃣ 对上面的临时表进行笛卡尔积并过滤无效信息
mysql> select * from dept t1, (select deptno, count(*) dep_num from emp group by deptno) t2 where t1.deptno=t2.deptno;+--------+------------+----------+--------+---------+| deptno | dname| loc| deptno | dep_num |+--------+------------+----------+--------+---------+| 10 | ACCOUNTING | NEW YORK | 10 | 3 || 20 | RESEARCH | DALLAS | 20 | 5 || 30 | SALES| CHICAGO| 30 | 6 |+--------+------------+----------+--------+---------+3 rows in set (0.00 sec)
3️⃣ 提取想要打印的信息
mysql> select t1.dname, t1.loc, t2.dep_num, t1.deptno from dept t1, (select deptno, count(*) dep_num from emp group by deptno) t2 where t1.deptno=t2.deptno;+------------+----------+---------+--------+| dname| loc| dep_num | deptno |+------------+----------+---------+--------+| ACCOUNTING | NEW YORK | 3 | 10 || RESEARCH | DALLAS | 5 | 20 || SALES| CHICAGO| 6 | 30 |+------------+----------+---------+--------+3 rows in set (0.00 sec)
七、合并查询
在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all。注意左右两边的select所查询的字段要相同。
7.1 union(并集+去重)
合并成个整体并且对蓝色部分去重。
- 找出工资大于2500或职位是MANAGER的人
mysql> select * from emp where sal > 2500 union select * from emp where job='MANAGER';+-------+-------+-----------+------+---------------------+---------+------+--------+| empno | ename | job | mgr| hiredate| sal | comm | deptno |+-------+-------+-----------+------+---------------------+---------+------+--------+|7566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL | 20 ||7698 | BLAKE | MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 | NULL | 30 ||7788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL | 20 ||7839 | KING| PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL | 10 ||7902 | FORD| ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL | 20 ||7782 | CLARK | MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 | NULL | 10 |+-------+-------+-----------+------+---------------------+---------+------+--------+6 rows in set (0.00 sec)
7.2 union all(并集+不去重)
- 将工资大于25000或职位是MANAGER的人找出来(取并集)
mysql> select * from emp where sal > 2500 union all select * from emp where job='MANAGER';+-------+-------+-----------+------+---------------------+---------+------+--------+| empno | ename | job | mgr| hiredate| sal | comm | deptno |+-------+-------+-----------+------+---------------------+---------+------+--------+|7566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL | 20 ||7698 | BLAKE | MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 | NULL | 30 ||7788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL | 20 ||7839 | KING| PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL | 10 ||7902 | FORD| ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL | 20 ||7566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL | 20 ||7698 | BLAKE | MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 | NULL | 30 ||7782 | CLARK | MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 | NULL | 10 |+-------+-------+-----------+------+---------------------+---------+------+--------+8 rows in set (0.01 sec)