经典SQL学习笔记 (四)-子查询

子查询

当一个查询是另一个查询的条件时,称之为子查询。子查询可以使用几个简单命令构造功能强大的复合命令。子查询最常用于SELECT-SQL命令的WHERE子句中。子查询是一个 SELECT 语句,它嵌套在一个 SELECT、SELECT…INTO 语句、INSERT…INTO 语句、DELETE 语句、或 UPDATE 语句或嵌套在另一子查询中
经典SQL学习笔记 (四)-子查询_第1张图片

单列子查询

例:查询工资比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;

你可能感兴趣的:(SQL结构化查询)