目录
[4.1 单行子查询(子查询结果为单列单行)](#4.1 单行子查询(子查询结果为单列单行))
[4.2 多行子查询(子查询结果为单列多行)](#4.2 多行子查询(子查询结果为单列多行))
[4.3 多列子查询](#4.3 多列子查询)
[4.4 在FROM子句中使用子查询](#4.4 在FROM子句中使用子查询)
一、基本查询回顾
sql
SHOW DATABASES;
USE test_select;
USE scott;
-- 基本查询回顾
-- 查询工资高于500或岗位为MANAGER的雇员,同时还需要满足他们的姓名首字母大写为J
SELECT * FROM emp;
SELECT * FROM emp WHERE (sal > 500 OR job = 'MANAGER') AND SUBSTRING(ename,1,1) = 'J';
SELECT * FROM emp WHERE (sal > 500 OR job = 'MANAGER') AND SUBSTRING(ename,1,2) = 'JA';
-- 按照部门号升序而雇员工资降序进行排序
SELECT * FROM emp ORDER BY deptno ASC,sal DESC;
SELECT ename,sal,deptno FROM emp ORDER BY deptno ASC,sal DESC;
-- 使用年薪进行降序排序
SELECT * FROM emp;
SELECT * FROM emp WHERE ename = 'SMITH';
SELECT sal*12 年薪 FROM emp WHERE ename = 'SMITH';
SELECT sal*12+comm 年薪 FROM emp WHERE ename = 'SMITH';
SELECT sal*12+IFNULL(comm,0) 年薪 FROM emp WHERE ename = 'SMITH';
SELECT sal*12+IFNULL(comm,0) 年薪 FROM emp;
SELECT sal*12+IFNULL(comm,0) 年薪 FROM emp ORDER BY 年薪 DESC;
-- 显示工资最高的员工的名字和工作岗位
SELECT MAX(sal) FROM emp;
SELECT * FROM emp WHERE sal = 5000;
SELECT * FROM emp WHERE sal = (SELECT MAX(sal) FROM emp);
SELECT ename,job FROM emp WHERE sal = (SELECT MAX(sal) FROM emp);
-- 显示每个部门的平均工资和最高工资
SELECT AVG(sal) 平均工资 FROM emp;
SELECT * FROM emp WHERE sal > (SELECT AVG(sal) FROM emp);
SELECT MAX(sal),AVG(sal) FROM emp;
SELECT MAX(sal) 最高,AVG(sal) 平均 FROM emp;
SELECT MAX(sal) 最高,AVG(sal) 平均 FROM emp GROUP BY deptno;
SELECT deptno,MAX(sal) 最高,AVG(sal) 平均 FROM emp GROUP BY deptno;
SELECT deptno,FORMAT(MAX(sal),2) 最高,FORMAT(AVG(sal),2) 平均 FROM emp GROUP BY deptno;
-- 显示平均工资低于2000的部门号和它的平均工资
SELECT AVG(sal) FROM emp;
SELECT AVG(sal) FROM emp GROUP BY deptno;
SELECT AVG(sal) 平均工资 FROM emp GROUP BY deptno;
SELECT deptno,AVG(sal) 平均工资 FROM emp GROUP BY deptno HAVING 平均工资<2000;
-- 显示每种岗位的雇员总数以及平均工资
SELECT job 岗位,COUNT(*) 雇员总数,FORMAT(AVG(sal),2) 平均工资 FROM emp GROUP BY job;
二、多表查询
多表查询步骤:
1.从第一张表中选出第一条记录,和第二张表的所有记录进行组合;
2.然后从第一张表中取第二条记录,和第二张表中的所有记录组合;
3.不加过滤条件,得到的结果为笛卡尔积;
例如SQL语句:
sql
SELECT * FROM emp,dept;

sql
-- 多表查询
-- 显示雇员名,雇员工资以及所在部门的名字
SELECT * FROM emp;
SELECT * FROM dept;
SELECT * FROM emp,dept;
SELECT * FROM emp,dept WHERE emp.deptno = dept.deptno;
-- 显示部门号为10的部门名,员工名和工资
SELECT * FROM emp,dept WHERE emp.deptno = dept.deptno;
SELECT ename,dname,sal FROM emp,dept WHERE emp.deptno = dept.deptno AND emp.deptno = 10;
-- 显示各个员工的姓名、工资以及工资级别
SELECT * FROM emp;
SELECT * FROM salgrade;
SELECT * FROM emp,salgrade;
SELECT * FROM emp,salgrade WHERE sal BETWEEN losal AND hisal;
SELECT ename,sal,grade FROM emp,salgrade WHERE sal BETWEEN losal AND hisal;
SELECT * FROM emp t1,salgrade t2;
SELECT * FROM emp AS t1,salgrade AS t2;
三、自连接
自连接指的是对同一张表进行连接查询。
sql
-- 自连接
-- 显示员工FORD的上级领导的编号和姓名
-- 方法1:子查询
SELECT * FROM emp;
SELECT mgr FROM emp WHERE ename = 'FORD';
SELECT ename,empno FROM emp WHERE mgr = 7566;
SELECT ename,empno FROM emp WHERE empno = 7566;
SELECT ename,empno FROM emp WHERE empno = (SELECT mgr FROM emp WHERE ename = 'FORD');
-- 方法2:自连接
SELECT * FROM emp e1,emp e2;
SELECT * FROM emp e1,emp e2 WHERE e1.ename = 'FORD';
SELECT * FROM emp e1,emp e2 WHERE e1.ename = 'FORD' AND e1.mgr = e2.empno;
SELECT e1.ename,e1.empno FROM emp e1,emp e2 WHERE e1.ename = 'FORD' AND e1.mgr = e2.empno;
四、子查询
子查询指的是SELECT语句嵌套在其它SQL语句中所形成的SELECT语句。
子查询一班出现在两个地方:
1.在WHERE子句中充当条件判断语句;
2.在FROM语句中作为临时表进行多表查询(笛卡尔积);
4.1 单行子查询(子查询结果为单列单行)
sql
-- 子查询
-- 单行子查询
-- 显示与SMITH同一部门的员工
SELECT * FROM emp WHERE ename = 'SMITH';
SELECT deptno FROM emp WHERE ename = 'SMITH';
SELECT * FROM emp WHERE deptno = 20;
SELECT * FROM emp WHERE deptno = (SELECT deptno FROM emp WHERE ename = 'SMITH');
SELECT ename FROM emp WHERE deptno = (SELECT deptno FROM emp WHERE ename = 'SMITH');
4.2 多行子查询(子查询结果为单列多行)
sql
-- 多行子查询
-- 查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10号部门自己的
-- 10号部门的工作岗位不止一个,要用IN关键字
SELECT job FROM emp WHERE deptno = 10;
SELECT DISTINCT job FROM emp WHERE deptno = 10;
SELECT ename,job,sal,deptno FROM emp WHERE job IN (SELECT DISTINCT job FROM EMP WHERE deptno = 10);
SELECT ename,job,sal,deptno FROM emp WHERE job IN (SELECT DISTINCT job FROM EMP WHERE deptno = 10) AND deptno <> 10;
SELECT * FROM (SELECT ename,job,sal,deptno FROM emp WHERE job IN (SELECT DISTINCT job FROM EMP WHERE deptno = 10) AND deptno <> 10) AS tmp,dept;
SELECT * FROM (SELECT ename,job,sal,deptno FROM emp WHERE job IN (SELECT DISTINCT job FROM EMP WHERE deptno = 10) AND deptno <> 10) AS tmp,dept WHERE tmp.deptno = dept.deptno;
SELECT ename,dname,job,sal,tmp.deptno FROM (SELECT ename,job,sal,deptno FROM emp WHERE job IN (SELECT DISTINCT job FROM EMP WHERE deptno = 10) AND deptno <> 10) AS tmp,dept WHERE tmp.deptno = dept.deptno;
-- ALL关键字;显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号
SELECT MAX(sal) FROM emp WHERE deptno = 30;
SELECT ename,sal,deptno FROM emp WHERE sal > 2850;
SELECT ename,sal,deptno FROM emp WHERE sal > (SELECT MAX(sal) FROM emp WHERE deptno = 30);
SELECT DISTINCT sal FROM emp WHERE deptno = 30;
SELECT ename,sal,deptno FROM emp WHERE sal > ALL(SELECT DISTINCT sal FROM emp WHERE deptno = 30);
-- ANY关键字;显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工)
SELECT DISTINCT sal FROM emp WHERE deptno = 30;
SELECT ename,sal,deptno FROM emp WHERE sal > ANY (SELECT DISTINCT sal FROM emp WHERE deptno = 30);
4.3 多列子查询
sql
-- 多行单列子查询:=
SELECT ename FROM emp WHERE (deptno,job) = (SELECT deptno,job FROM emp WHERE ename = 'SMITH') AND ename <> 'SMITH';
-- 多行多列子查询:IN
SELECT ename FROM emp WHERE (deptno,job) IN (SELECT deptno,job FROM emp WHERE ename = 'SMITH') AND ename <> 'SMITH';
4.4 在FROM子句中使用子查询
sql
-- FROM子句中使用子查询
-- 显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资
SELECT AVG(sal) FROM emp;
SELECT AVG(sal) FROM emp GROUP BY deptno;
SELECT deptno,AVG(sal) FROM emp GROUP BY deptno;
SELECT * FROM emp,(SELECT deptno,AVG(sal) FROM emp GROUP BY deptno) tmp;
SELECT * FROM emp,(SELECT deptno,AVG(sal) FROM emp GROUP BY deptno) tmp WHERE emp.deptno = tmp.deptno;
SELECT * FROM emp,(SELECT deptno,AVG(sal) FROM emp GROUP BY deptno) tmp WHERE emp.deptno = tmp.deptno AND emp.sal > tmp.AVG(sal);
SELECT * FROM emp,(SELECT deptno,AVG(sal) myavg FROM emp GROUP BY deptno) tmp WHERE emp.deptno = tmp.deptno AND emp.sal > tmp.myavg;
SELECT ename,emp.deptno,sal,myavg FROM emp,(SELECT deptno,AVG(sal) myavg FROM emp GROUP BY deptno) tmp WHERE emp.deptno = tmp.deptno AND emp.sal > tmp.myavg;
SELECT * FROM dept,(SELECT ename,emp.deptno,sal,myavg FROM emp,(SELECT deptno,AVG(sal) myavg FROM emp GROUP BY deptno) tmp WHERE emp.deptno = tmp.deptno AND emp.sal > tmp.myavg) t1;
SELECT * FROM dept,(SELECT ename,emp.deptno,sal,myavg FROM emp,(SELECT deptno,AVG(sal) myavg FROM emp GROUP BY deptno) tmp WHERE emp.deptno = tmp.deptno AND emp.sal > tmp.myavg) t1 WHERE dept.deptno = t1.deptno;
SELECT t1.ename,dept.loc,t1.deptno FROM dept,(SELECT ename,emp.deptno,sal,myavg FROM emp,(SELECT deptno,AVG(sal) myavg FROM emp GROUP BY deptno) tmp WHERE emp.deptno = tmp.deptno AND emp.sal > tmp.myavg) t1 WHERE dept.deptno = t1.deptno;
-- 查找每个部门工资最高的人的姓名、工资、部门、最高工资
SELECT MAX(sal) FROM emp GROUP BY deptno;
SELECT deptno,MAX(sal) FROM emp GROUP BY deptno;
SELECT * FROM emp t1,(SELECT deptno,MAX(sal) FROM emp GROUP BY deptno) t2;
SELECT * FROM emp t1,(SELECT deptno,MAX(sal) FROM emp GROUP BY deptno) t2 WHERE t1.deptno = t2.deptno;
SELECT * FROM emp t1,(SELECT deptno,MAX(sal) mymax FROM emp GROUP BY deptno) t2 WHERE t1.deptno = t2.deptno AND t1.sal = t2.mymax;
SELECT t1.ename,t1.sal,t1.deptno,t2.mymax FROM emp t1,(SELECT deptno,MAX(sal) mymax FROM emp GROUP BY deptno) t2 WHERE t1.deptno = t2.deptno AND t1.sal = t2.mymax;
-- 显示每个部门的信息和人员数量
SELECT COUNT(*) FROM emp GROUP BY deptno;
SELECT deptno,COUNT(*) FROM emp GROUP BY deptno;
SELECT * FROM dept t1,(SELECT deptno,COUNT(*) FROM emp GROUP BY deptno) t2;
SELECT * FROM dept t1,(SELECT deptno,COUNT(*) FROM emp GROUP BY deptno) t2 WHERE t1.deptno = t2.deptno;
五、合并查询
在实际应用中,为了合并多个SELECT执行结果,可以使用操作符UNION、UNION ALL,两者的区别为:
1.UNION用于取得两个结果集的并集,会自动去掉结果集中的重复行;
2.UNION ALL用于取得两个结果集的并集,不会去掉结果集中的重复行;
sql
-- 合并查询
-- 将工资大于2500或职位是MANAGER的人找出来
SELECT * FROM emp WHERE sal > 2500;
SELECT * FROM emp WHERE job = 'MANAGER';
SELECT * FROM emp WHERE sal > 2500 UNION SELECT * FROM emp WHERE job = 'MANAGER';
SELECT * FROM emp WHERE sal > 2500 UNION ALL SELECT * FROM emp WHERE job = 'MANAGER';
