08子查询

先看以下子查询的执行顺序:

5select (distinct) 列名【别名】,列名【别名】,

5select (distinct) 列名【别名】,列名【别名】

1 from 表名【别名】

2【Where 条件限定】;

3 GROUP BY

4 HAVING 字句

6ORDER BY 列名 ASC/DESC

1 from 表名【别名】,表名【别名】,

5select (distinct) 列名【别名】,列名【别名】

1 from 表名【别名】

2【Where 条件限定】;

3 GROUP BY

4 HAVING 字句

6ORDER BY 列名 ASC/DESC

2【Where 条件限定】,

5select (distinct) 列名【别名】,列名【别名】

1 from 表名【别名】

2【Where 条件限定】;

3 GROUP BY

4 HAVING 字句

6ORDER BY 列名 ASC/DESC

3 GROUP BY 分组字段,分组字段,

5select (distinct) 列名【别名】,列名【别名】

1 from 表名【别名】

2【Where 条件限定】;

3 GROUP BY

4 HAVING 子句

6ORDER BY 列名 ASC/DESC

4 HAVING 子句,

5select (distinct) 列名【别名】,列名【别名】

1 from 表名【别名】

2【Where 条件限定】;

3 GROUP BY

4 HAVING 字句

6ORDER BY 列名 ASC/DESC

6 ORDER BY 列名 ASC/DESC,

5select (distinct) 列名【别名】,列名【别名】

1 from 表名【别名】

2【Where 条件限定】;

3 GROUP BY

4 HAVING 字句

6ORDER BY 列名 ASC/DESC

子查询都需要使用“()”声明,所谓的子查询就是属于查询嵌套,出现子查询最多的位置:WHERE,FROM;

针对子查询出现给出几个参考方案:

WHERE:子查询返回单行单列,单行多列,多行单列

HAVING:单行单列并且需要统计函数过滤时

FROM:多行多列

SELECT:返回单行单列并且需要某些查询的时候

WHERE:子查询返回单行单列,单行多列,多行单列

WHERE单行单列

例:查找出公司工资最低的雇员信息

--工资最低用MIN()

SELECT MIN(sal) FROM emp;

--统计出最低工资的雇员

SELECT * (雇员信息)

FROM EMP

WHERE sal=(SELECT MIN(sal) FROM emp);

WHERE单行多列(了解)

例:查询出与我们scott工资相同和职位相同的所有雇员信息

--比较工资与职位,同时,先查询scott的工资与职位

SELECT *

FROM emp

WHERE (sal,job)=( SELECT sal,job FROM emp WHERE ename='Scott')

AND ename<>'Scott';

WHERE子查询多行单列(重点)

相当于告诉用户一个数据的操作范围,如果要进行范围的判断,where提供三个运算符,IN,ANY,ALL

1.IN

IN操作指的是内容可以在指定范围内存在

例:查询出与经理职位工资相同的雇员

SELECT * FROM emp

WHERE sal IN

(SELECT sal FROM emp WHERE job='MANAGER');

SELECT * FROM emp

WHERE sal NOT IN--不能为空

(SELECT sal FROM emp WHERE job='MANAGER');

NOT IN不能为空的概念在这里也适用,例如 SELECT * FROM emp WHERE comm NOT IN (SELECT comm FROM emp);--这个操作必须保证子查询SELECT comm FROM emp里面没有空,不然会出现未返回值的情况;

 ANY操作

=ANY

SELECT * FROM emp

WHERE sal =ANY

(SELECT sal FROM emp WHERE job='MANAGER');

>ANY:比子查询中最小的查询要大

SELECT * FROM emp

WHERE sal >ANY

(SELECT sal FROM emp WHERE job='MANAGER');

 <ANY:比子查询中最大的值要小

SELECT * FROM emp

WHERE sal  <ANY

(SELECT sal FROM emp WHERE job='MANAGER');

 ALL操作

 >ALL比子查询中返回的最大的值要大

<ALL比子查询中返回的最小的值要小

exists()判断

SELECT * FROM emp

WHERE EXISTS

(SELECT * FROM emp WHERE empno=7389);--如果有数据返回就返回SELECT * FROM emp

如果SELECT * FROM emp WHERE empno=7389是有数据的,则使用exists后的子查询是会显示数据出来的;EXISTS之关系子查询里面返回的是否有行,至于什么行不关系。

HAVING:单行单列并且需要统计函数过滤时

必须要结合GROUP BY字句,

例:要求统计出所有高于公司平均工资的部门编号,平均工资及部门人数;

--先统计出根据部门编号的平均工资和部门人数

SELECT deptno,COUNT(*),AVG(sal)

FROM emp

GROUP BY deptno;

--再统计出公司平均工资

SELECT AVG(sal) FROM emp;--子查询单行单列涉及到WHERE和HAVING字句

--因涉及统计函数过滤,要用HAVING

SELECT deptno,COUNT(*),AVG(sal)

FROM emp

GROUP BY deptno

HAVING AVG(sal)>( SELECT AVG(sal) FROM emp);

SELECT:返回单行单列并且需要某些查询的时候

多表查询可以用子查询:

查询雇员名称、职位、部门名称

SELECT e.ename,e.job,d.dname

FROM emp e,dept d

WHERE e.deptno=d.deptno;

转换为

SELECT e.ename,e.job,(SELECT dname FROM dept d WHERE d.deptno=e.deptno)

FROM emp e;

FROM:多行多列(重点)

 例:查询每个部门的编号、名称、位置、部门人数、平均工资

SELECT d.deptno,d.dname,d.loc,COUNT(e.empno),AVG(e.sal)  --只能出现分组字段d.deptno,d.dname,d.loc

FROM emp e,dept d

WHERE e.deptno(+)=d.deptno

GROUP BY d.deptno,d.dname,d.loc;

 利用子查询:

-先查出部门编号、部门人数、平均工资

SELECT d.deptno,COUNT(empno),AVG(sal)

FROM emp

GROUP BY deptno;---当做一张多行多列的表,可作为FROM字句

--利用以上作为字句:

SELECT d.dname,d.loc,d.deptno,temp.count,temp.avg

FROM dept d,(

            SELECT d.deptno,COUNT(empno) count,AVG(sal) avg

            FROM emp

           GROUP BY deptno) temp

WHERE d.deptno=temp.deptno(+);

 

复杂查询案例:

1.列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金,部门名称,部门人数;

--确定要使用的数据表

emp表:员工姓名和薪金

dept表:部门名称

统计函数:部门人数

--确定关联字段

emp.deptno=dept.deptno;

--找出部门30所有员工的薪金,可以得出这是个多行单列的子查询操作,如果要进行范围的判断,where提供三个运算符,IN,ANY,ALL

--如果案例中出现高于、低于、大于、小于、等于等字眼,则可考虑范围查询,使用WHERE字句和运算符,并且先将范围列出来:在部门30工作的所有员工的薪金

SELECT sal

FROM emp

WHERE deptno=30;

--薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金

SELECT e.sal,e.ename

FROM emp e

WHERE e.sal>ALL(

                    SELECT sal

                    FROM emp

                   WHERE deptno=30) temp;

-- 薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金,部门名称;

SELECT e.sal,e.ename,d.dname

FROM emp e,dept d

WHERE e.sal>ALL(

                    SELECT sal

                    FROM emp

                   WHERE deptno=30)

                   AND e.deptno=d.deptno;

--统计出部门人数的信息;要按照部门分组,使用分组GROUP BY时SELECT字句只能出现分组字段和统计函数,但是此时SELECT字句出现了其他字段e.sal,e.ename,d.dname,只能考虑子查询,即用FROM中使用字查询得出新的一张表;

SELECT e.sal,e.ename,d.dname,temp.count
FROM emp e,dept d,(
                     SELECT deptno dno,COUNT(empno) count
                     FROM emp
                     GROUP BY deptno) temp
WHERE e.sal>ALL(
                    SELECT sal
                    FROM emp
                   WHERE deptno=30)
                   AND e.deptno=d.deptno
                   AND d.deptno=temp.dno;​

2.列出与‘Scott'从事相同工作的所有员工及部门名称、部门人数、领导姓名

--确定要使用的数据表

emp表:员工信息

dept表:部门名称

emp表:领导信息

统计函数:部门人数

--确定关联字段

 雇员与emp.deptno=dept.deptno;

雇员与领导:emp.mgr(领导编号)=memp.empno;

empno(雇员编号)

mgr(领导编号)

 --列出Scott从事的工作,单行单列,只能在WHERE 或Having中使用

SELECT job
FROM emp
WHERE ename='Scott';​

 --与‘Scott'从事相同工作的所有员工名称及所在部门名称、部门人数、领导姓名

SELECT e.ename,d.dname,temp1.count,m.ename
FROM emp e,dept d,(
    SELECT deptno dno,COUNT(empno) count FROM emp
    GROUP BY deptno) temp1,emp m
    
WHERE job=(
    SELECT job
    FROM emp
    WHERE ename='Scott')
    AND e.ename<>'Scott'
    AND e.deptno=d.deptno
    AND d.deptno=temp1.dno
    AND e.mgr=m.empno;

3.列出薪金比‘Smith’或‘ALLEN’多的所有员工的编号、姓名、部门名称、其领导姓名、部门人数,平均工资,最高及最低工资;

--数据表:emp表、dept表,统计函数包括部门人数,平均工资,最高及最低工资;

#查出‘Smith’或‘ALLEN’的薪金,多行单列
SELECT sal
FROM emp
WHERE ename IN('SMITH','ALLEN');

#查出比‘Smith’或‘ALLEN’任意一个多的员工信息并抛出‘Smith’和‘ALLEN’,e.mgr=m.empno查询领导姓名

SELECT e.name,e.empno,e.sal,d.dname,m.ename,temp.count,temp.avg,temp.max
FROM emp e,dept d,emp m,(
    SELECT deptno dno,COUNT(empno) count AVG(sal) avg ,MAX(sal) max
    FROM emp
    GROUP BY deptno) temp
WHERE e.sal> ANY(
    SELECT sal
    FROM emp
    WHERE ename IN('SMITH','ALLEN'))
    AND e.ename NOT IN('SMITH','ALLEN')
    AND e.deptno=d.deptno
    AND e.mgr=m.empno(+)
    AND temp.dno=d.deptno;
    
    

4.找出职位为‘CLERK'的员工编号、姓名、所在部门名称、部门人数、工资等级

SELECT e.name,e.empno,d.name,temp.count,s.grade
FROM emp e,dept d,(
    SELECT deptno dno,COUNT(empno)
     FROM emp
    GROUP BY deptno) temp,salegrade s
WHERE e.job='CLERK' 
    AND e.deptno=d.deptno
    AND d.deptno=temp.dno
    AND e.sal BETWEEN s.losal AND s.hisal;

猜你喜欢

转载自blog.csdn.net/weixin_41556724/article/details/86062714