当一个查询是另一个查询的条件时,称之为子查询。子查询可以使用几个简单命令构造功能强大的复合命令。子查询最常用于SELECT-SQL命令的WHERE子句中。子查询是一个 SELECT 语句,它嵌套在一个 SELECT、SELECT…INTO 语句、INSERT…INTO 语句、DELETE 语句、或 UPDATE 语句或嵌套在另一子查询中
单列子查询
例:查询工资比7788高的雇员信息
--方式一:通过多表联接查询实现
SELECT E1.*
FROM EMP E1,EMP E2
WHERE E2.EMPNO=7788 AND E1.SAL>E2.SAL;
--方式二:子查询--
SELECT * FROM EMP WHERE SAL>
(SELECT SAL FROM EMP WHERE EMPNO=7788);
例:查询工资比部门20员工的工资高的雇员信息
SELECT * FROM EMP WHERE SAL>
(SELECT SAL FROM EMP WHERE DEPTNO=20);
select sal from emp where deptno=20;
select * from emp where sal>(select sal from emp where deptno=20); X
--注:将子查询和比较运算符一起使用时,必须保证子查询返回的值不能多于一个
例:查询雇员编号、雇员姓名、所在部门名称
--方式一:多表联接查询
SELECT EMPNO 雇员编号,ENAME 雇员姓名,DNAME 部门名称
FROM EMP E,DEPT D
WHERE E.DEPTNO=D.DEPTNO;
--方式二:子查询
SELECT EMPNO ¹ÍÔ±±àºÅ,ENAME ¹ÍÔ±ÐÕÃû,
(SELECT DNAME FROM DEPT WHERE DEPTNO=EMP.DEPTNO) ²¿ÃÅÃû³Æ
FROM EMP;
--注:很多时候,多表联接查询和子查询都可以互相替换,所有的多表联接查询都可以使用子查询替换,但有的子查询无法使用多表联接替换
--多表联接查询更适合于进行多张表之间数据的检索
--子查询比较灵活,功能比较强大,多作为数据检索的条件
2)子查询分类
单列子查询:返回单行单列,使用频率最高
多行子查询:返回多行单列
多列子查询:返回单行多列或多行多列
-----单列子查询-----
例:查询工资比7654高,同时又与7369从事相同工作的雇员信息
SELECT * FROM EMP WHERE SAL>
(SELECT SAL FROM EMP WHERE EMPNO=7654)
AND JOB =(SELECT JOB FROM EMP WHERE EMPNO=7369);
例:查询工资最低的雇员的姓名、工作、工资
SELECT ENAME,JOB,SAL FROM EMP WHERE SAL=
(SELECT MIN(SAL) FROM EMP);
例:查询工资高于公司平均工资的雇员信息
SELECT * FROM EMP WHERE SAL>
(SELECT AVG(SAL) FROM EMP);
例:按部门进行分组,查询部门的编号和最低工资,要求最低工资大于等于部门30的最低工资
SELECT DEPTNO,MIN(SAL) FROM EMP
GROUP BY DEPTNO
HAVING MIN(SAL)>=(SELECT MIN(SAL) FROM EMP WHERE DEPTNO=30);
例:查询平均工资最低的工作及平均工资
SELECT JOB, MIN(SAL)
FROM EMP
GROUP BY JOB
HAVING AVG(SAL)=(SELECT MIN(AVG(SAL)) FROM EMP GROUP BY JOB);
多行子查询
多行单列
三种符号,用来操作多行单列的结果
IN
例:查询所在部门编号大于20的雇员信息
SELECT * FROM EMP WHERE DEPTNO IN
(SELECT DEPTNO FROM EMP WHERE DEPTNO>20);
例:查询工资与部门10的任意员工相同的雇员信息
SELECT * FROM EMP WHERE SAL IN
(SELECT SAL FROM EMP WHERE DEPTNO=10);
ANY
=ANY 与IN操作符作用相同
SELECT * FROM EMP WHERE SAL =ANY (SELECT SAL FROM EMP WHERE DEPTNO=10);
>ANY 比里面的最小值大
SELECT * FROM EMP WHERE SAL >ANY (SELECT SAL FROM EMP WHERE DEPTNO=10);
SELECT * FROM EMP WHERE SAL SELECT SAL FROM EMP WHERE DEPTNO=10);
ALL
>ALL 比里面的最大值大
SELECT * FROM EMP WHERE SAL >ALL (SELECT SAL FROM EMP WHERE DEPTNO=10);
SELECT * FROM EMP WHERE SAL SELECT SAL FROM EMP WHERE DEPTNO=10);
多列子查询:返回单行多列或多行多列
例:查询工资、奖金与SMITH完全相同的雇员信息
SELECT * FROM EMP
WHERE (SAL,NVL(COMM,0)) IN (SELECT SAL,NVL(COMM,0) FROM EMP WHERE ENAME='SMITH');
子查询
1、列出至少有一个员工的所有部门
SELECT D.DNAME,COUNT(E.EMPNO)
FROM EMP E,DEPT D
WHERE E.DEPTNO=D.DEPTNO
GROUP BY D.DNAME
HAVING COUNT(E.EMPNO)>1;
2、列出薪金比“SMITH”多的所有员工
SELECT * FROM EMP WHERE SAL>
(SELECT SAL FROM EMP WHERE ENAME='SMITH');
3、列出所有“CLERK”的姓名及其部门名称,部门的人数
SELECT D.DNAME,E.ENAME
FROM EMP E,DEPT D
WHERE E.DEPTNO=D.DEPTNO AND JOB='CLERK';
SELECT E.ENAME,D.DNAME,TEMP.COU
FROM(SELECT DEPTNO, COUNT(*) FROM EMP GROUP BY DEPTNO) TEMP,EMP E,DEPT D
WHERE TEMP.DEPTNO=E.DEPTNO AND
select e.ename,d.dname,tmp.count
from emp e,dept d,(select deptno,count(empno) count from emp group by deptno) tmp
where e.deptno=d.deptno and e.job='CLERK' and d.deptno=tmp.deptno;
4、列出最低薪金大于1500的各种工作及此从事此工作的全部雇员人数
select job,count(empno)
from emp
where sal>1500
group by job;
5、列出在部门“sales”(销售部)工作的员工的姓名,假定不知道销售部的部门编号
select ename
from emp
where deptno=(select deptno from dept where dname='SALES');
6、列出薪金高于公司平均薪金的所有员工,所在部门,上级领导等级,公司的工资等级
select e.ename,d.dname,m.ename,g.grade
from emp e,emp m,dept d,salgrade g
where e.mgr=m.empno and e.sal>(select avg(sal) from emp)
and e.deptno=d.deptno and e.sal between g.losal and g.hisal;
7、列出与“scott”从事相同工作的所有员工及部门名称
SELECT E.*,D.DNAME
FROM EMP E,DEPT D
WHERE E.DEPTNO=D.DEPTNO AND JOB= (SELECT JOB FROM EMP WHERE ENAME='SCOTT');
8、列出薪金等于部门30中员工的薪金的所有员工的姓名和薪金
SELECT ENAME, SAL
FROM EMP
WHERE SAL IN (SELECT SAL FROM EMP WHERE DEPTNO=30);
9、列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金,部门名称
SELECT E.ENAME ,E.SAL ,D.DNAME
FROM EMP E, DEPT D
WHERE E.DEPTNO=D.DEPTNO AND E.SAL > ALL (SELECT MAX(SAL) FROM EMP WHERE DEPTNO=30);
10、列出在每个部门工作的员工数量、平均工资和平均服务期限
SELECT COUNT(EMPNO),ROUND(AVG(SAL)),ROUND(AVG(MONTHS_BETWEEN(SYSDATE,HIREDATE))/12)
FROM EMP
GROUP BY DEPTNO;
11、列出所有部门的详细信息和部门人数
select d.*,temp.count
from dept d,(select deptno,count(empno) count from emp group by deptno) temp
where d.deptno=temp.deptno(+);
16、列出各种工作的最低工资以及从事此工作的雇员姓名
select e.ename,temp.job,e.sal
from emp e,(select job,min(sal) min from emp group by job) temp
where e.job=temp.job and e.sal=temp.min;
17、列出各个部门的经理的最低薪金
select deptno,min(sal)
from emp
where job='MANAGER'
group by deptno;
18、求出部门名称中,带'S'字符的部门员工的工资总和 、部门人数
SELECT D.DNAME,SUM(SAL),COUNT(EMPNO)
FROM EMP E,DEPT D
WHERE E.DEPTNO=D.DEPTNO AND D.DNAME LIKE '%S%'
GROUP BY D.DNAME;