Oracle-子查询和集合运算

子查询

子查询:sub query, 查询是在某个查询结果之上进行的。(一条select语句内部包含了另外一条select语句)
在这里插入图片描述
在这里插入图片描述

子查询类型

在这里插入图片描述

1.单行子查询

在这里插入图片描述
举一个例子,查询职位为MANAGER,薪水大于2450的员工。
通过下面 的例子可以知道两点:

  • 单行子查询只能使用单行操作符
  • 主查询和子查询是1:N的关系
SQL> select ename,job,sal
  2  from emp
  3  where job = (select job
  4               from emp
  5               where empno = 7566)
  6  and sal > (select sal
  7             from emp
  8             where empno = 7782);
ENAME      JOB              SAL
---------- --------- ----------
JONES      MANAGER         2975
BLAKE      MANAGER         2850
SQL> --查询工资比SCOTT高的员工信息
SQL> --1. SCOTT的工资
SQL> select sal from emp where ename='SCOTT';
       SAL                                                                                                                                                                                              
----------                                                                                                                                                                                              
      3000                                                                                                                                                                                              

SQL> --2. 查询比3000高的员工
SQL> select * from emp where sal >3000;
     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO                                                                                                              
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------                                                                                                              
      7839 KING       PRESIDENT            17-11月-81           5000                    10  

SQL> --子查询所要解决的问题:不能一步求解
SQL> select * from emp
  2  where sal > (select sal
  3               from emp
  4               where ename='SCOTT');
     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
      7839 KING       PRESIDENT            17-11月-81           5000                    10

2.多行子查询

在这里插入图片描述

  • 多行子查询只能使用多行操作符
  • 主查询和子查询是1:N的关系

1.in:等于列表中的任何一个

SQL> --查询部门为SALES和ACCOUNTING的员工(方式一)
SQL> select empno,ename,sal
  2  from emp
  3  where deptno in (select deptno
  4            from dept
  5            where dname = 'ACCOUNTING' or dname = 'SALES');
     EMPNO ENAME             SAL
---------- ---------- ----------
      7499 ALLEN            1600
      7521 WARD             1250
      7654 MARTIN           1250
      7698 BLAKE            2850
      7782 CLARK            2450
      7839 KING             5000
      7844 TURNER           1500
      7900 JAMES             950
      7934 MILLER           1300
	  已选择 9 行。

SQL> --查询部门为SALES和ACCOUNTING的员工(方式二)
SQL> --sql不符合题目逻辑
SQL> select e.*
  2  from emp e,dept d
  3  where e.deptno = d.deptno
  4  and d.dname = 'ACCOUNTING' or dname = 'SALES';
     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
      7782 CLARK      MANAGER         7839 09-6月 -81           2450                    10
      7839 KING       PRESIDENT            17-11月-81           5000                    10
      7934 MILLER     CLERK           7782 23-1月 -82           1300                    10
      7369 SMITH      CLERK           7902 17-12月-80            800                    20
      7499 ALLEN      SALESMAN        7698 20-2月 -81           1600        300         30
      7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30
      7566 JONES      MANAGER         7839 02-4月 -81           2975                    20
      7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400         30
      7698 BLAKE      MANAGER         7839 01-5月 -81           2850                    30
      7782 CLARK      MANAGER         7839 09-6月 -81           2450                    10
      7788 SCOTT      ANALYST         7566 19-4月 -87           3000                    20
      7839 KING       PRESIDENT            17-11月-81           5000                    10
      7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0         30
      7876 ADAMS      CLERK           7788 23-5月 -87           1100                    20
      7900 JAMES      CLERK           7698 03-12月-81            950                    30
      7902 FORD       ANALYST         7566 03-12月-81           3000                    20
      7934 MILLER     CLERK           7782 23-1月 -82           1300                    10
      已选择 17 行。

SQL> --sql的d.dname = 'ACCOUNTING' or dname = 'SALES'要加上括号。
SQL> select e.*
  2  from emp e,dept d
  3  where e.deptno = d.deptno
  4  and (d.dname = 'ACCOUNTING' or dname = 'SALES');
     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
      7499 ALLEN      SALESMAN        7698 20-2月 -81           1600        300         30
      7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30
      7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400         30
      7698 BLAKE      MANAGER         7839 01-5月 -81           2850                    30
      7782 CLARK      MANAGER         7839 09-6月 -81           2450                    10
      7839 KING       PRESIDENT            17-11月-81           5000                    10
      7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0         30
      7900 JAMES      CLERK           7698 03-12月-81            950                    30
      7934 MILLER     CLERK           7782 23-1月 -82           1300                    10
      已选择 9 行。

2.any:和子查询返回的任意一个值做比较

SQL> --any: 和集合中的任意一个值比较。
SQL> --查询工资比30号部门任意一个员工高的员工信息。
SQL> select *
  2  from emp
  3  where sal > any(select sal
  4                  from emp
  5                  where deptno = 30);
     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
      7839 KING       PRESIDENT            17-11月-81           5000                    10
      7902 FORD       ANALYST         7566 03-12月-81           3000                    20
      7788 SCOTT      ANALYST         7566 19-4月 -87           3000                    20
      7566 JONES      MANAGER         7839 02-4月 -81           2975                    20
      7698 BLAKE      MANAGER         7839 01-5月 -81           2850                    30
      7782 CLARK      MANAGER         7839 09-6月 -81           2450                    10
      7499 ALLEN      SALESMAN        7698 20-2月 -81           1600        300         30
      7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0         30
      7934 MILLER     CLERK           7782 23-1月 -82           1300                    10
      7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30
      7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400         30
      7876 ADAMS      CLERK           7788 23-5月 -87           1100                    20
      已选择 12 行。

SQL> --any是和子查询返回的任意一个值做比较,根据题目要求只要比最小的大就可以满足条件了,下面的查询结果集和上面一样。
SQL> select *
  2  from emp
  3  where sal > (select min(sal)
  4                  from emp
  5                  where deptno = 30);
     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
      7499 ALLEN      SALESMAN        7698 20-2月 -81           1600        300         30
      7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30
      7566 JONES      MANAGER         7839 02-4月 -81           2975                    20
      7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400         30
      7698 BLAKE      MANAGER         7839 01-5月 -81           2850                    30
      7782 CLARK      MANAGER         7839 09-6月 -81           2450                    10
      7788 SCOTT      ANALYST         7566 19-4月 -87           3000                    20
      7839 KING       PRESIDENT            17-11月-81           5000                    10
      7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0         30
      7876 ADAMS      CLERK           7788 23-5月 -87           1100                    20
      7902 FORD       ANALYST         7566 03-12月-81           3000                    20
      7934 MILLER     CLERK           7782 23-1月 -82           1300                    10
      已选择 12 行。

3.all:和子查询返回的所有值作比较

SQL> --all:和集合中的所有值比较
SQL> --查询工资比30号部门所有员工高的员工信息
SQL> select *
  2  from emp
  3  where sal > all (select sal
  4                  from emp
  5                  where deptno = 30);
     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
      7566 JONES      MANAGER         7839 02-4月 -81           2975                    20
      7788 SCOTT      ANALYST         7566 19-4月 -87           3000                    20
      7839 KING       PRESIDENT            17-11月-81           5000                    10
      7902 FORD       ANALYST         7566 03-12月-81           3000                    20

SQL> --all是和子查询返回的所有值作比较,根据题目要求只要比最大的大就可以满足条件了,下面的查询结果集和上面一样。
SQL> select *
  2  from emp
  3  where sal >  (select max(sal)
  4                  from emp
  5                  where deptno = 30);

     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
      7566 JONES      MANAGER         7839 02-4月 -81           2975                    20
      7788 SCOTT      ANALYST         7566 19-4月 -87           3000                    20
      7839 KING       PRESIDENT            17-11月-81           5000                    10
      7902 FORD       ANALYST         7566 03-12月-81           3000                    20

子查询要注意的问题

1、括号
2、合理的书写风格
3、将子查询放在比较条件的右侧
4、可以在主查询的 where select having from 后面使用子查询
5、不可以在 group by 使用子查询
6、强调 from 后面的子查询
7、主查询和子查询可以不是同一张表;只有子查询返回的结果 主查询可以使用 即可
8、一般不在子查询中排序;但在top-n分析问题中 必须对子查询排序
9、一般先执行子查询,再执行主查询;但相关子查询例外
10、单行子查询只能使用单行操作符;多行子查询只能使用多行操作符
11、子查询中的null

4、可以在主查询的 select from where having 后面使用子查询
1.select后面使用子查询
SQL> --3、可以在主查询的where select having  from 后面使用子查询
SQL> select empno,ename,sal,(select job from emp where empno=7839) 第四列
  2  from emp;
     EMPNO ENAME             SAL 第四列                                                                                                                                                                 
---------- ---------- ---------- ---------                                                                                                                                                              
      7369 SMITH             800 PRESIDENT                                                                                                                                                              
      7499 ALLEN            1600 PRESIDENT                                                                                                                                                              
      7521 WARD             1250 PRESIDENT                                                                                                                                                              
      7566 JONES            2975 PRESIDENT                                                                                                                                                              
      7654 MARTIN           1250 PRESIDENT                                                                                                                                                              
      7698 BLAKE            2850 PRESIDENT                                                                                                                                                              
      7782 CLARK            2450 PRESIDENT                                                                                                                                                              
      7788 SCOTT            3000 PRESIDENT                                                                                                                                                              
      7839 KING             5000 PRESIDENT                                                                                                                                                              
      7844 TURNER           1500 PRESIDENT                                                                                                                                                              
      7876 ADAMS            1100 PRESIDENT                                                                                                                                                                                                                                                                                                                         
      7900 JAMES             950 PRESIDENT                                                                                                                                                              
      7902 FORD             3000 PRESIDENT                                                                                                                                                              
      7934 MILLER           1300 PRESIDENT                                                                                                                                                              
	  已选择 14 行。
2.where后面使用子查询
SQL> select *
  2  from emp
  3  where sal >(select sal
  4              from emp
  5              where ename='SCOTT');
     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
      7839 KING       PRESIDENT            17-11月-81           5000                    10
3.having后面使用子查询
SQL> --3、可以在主查询的where select having  from 后面使用子查询
SQL> --查询各部门中最低工资大于20号部门最低工资。
SQL> select deptno,min(sal)
  2  from emp
  3  group by deptno
  4  having min(sal) > (select min(sal)
  5         from emp
  6         where deptno = 20);
    DEPTNO   MIN(SAL)
---------- ----------
        30        950
        10       1300
5、不可以在 group by 使用子查询

查看group by字句,你怎么在后面加上子查询,也没办法加子查询。

SQL> select deptno
  2  from emp
  3  group by deptno;
    DEPTNO
----------
        30
        20
        10
6、强调 from 后面的子查询
SQL> --强调 from 后面的子查询
SQL> --查询员工信息:员工号 名称 薪水
SQL> /*
SQL> select *
SQL> ______________这个这个横线上怎么写,可以满足题目要求。	
SQL> */
SQL> select *
  2  from (select empno,ename,sal
  3        from emp);
     EMPNO ENAME             SAL
---------- ---------- ----------
      7369 SMITH             800
      7499 ALLEN            1600
      7521 WARD             1250
      7566 JONES            2975
      7654 MARTIN           1250
      7698 BLAKE            2850
      7782 CLARK            2450
      7788 SCOTT            3000
      7839 KING             5000
      7844 TURNER           1500
      7876 ADAMS            1100
      7900 JAMES             950
      7902 FORD             3000
      7934 MILLER           1300
	  已选择 14 行。

SQL> --查询员工信息:员工号 名称 薪水
SQL> /*
SQL> select *
SQL> ______________这个这个横线上怎么写,可以满足题目要求。	
SQL> */
SQL> select *
  2  from (select empno,ename,sal,sal*12
  3        from emp);
     EMPNO ENAME             SAL     SAL*12
---------- ---------- ---------- ----------
      7369 SMITH             800       9600
      7499 ALLEN            1600      19200
      7521 WARD             1250      15000
      7566 JONES            2975      35700
      7654 MARTIN           1250      15000
      7698 BLAKE            2850      34200
      7782 CLARK            2450      29400
      7788 SCOTT            3000      36000
      7839 KING             5000      60000
      7844 TURNER           1500      18000
      7876 ADAMS            1100      13200
      7900 JAMES             950      11400
      7902 FORD             3000      36000
      7934 MILLER           1300      15600
      已选择 14 行。
7、主查询和子查询可以不是同一张表;只要子查询返回的结果 主查询可以使用 即可
  • 如果子查询和多表查询都能完成的查询,尽量使用多表查询(因为子查询会访问操作数据库多次)。
  • 在Oracle数据库中,很多子查询最终会转为多表查询,那是怎么知道呢?通过–>SQL执行计划
SQL> --主查询和子查询可以不是同一张表;只要子查询返回的结果 主查询可以使用 即可
SQL> --查询部门名称是SALES的员工(方式一)
SQL> select *
  2  from emp
  3  where deptno=(select deptno from dept where dname='SALES');
     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO                                                                                                              
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------                                                                                                              
      7499 ALLEN      SALESMAN        7698 20-2月 -81           1600        300         30                                                                                                              
      7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30                                                                                                              
      7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400         30                                                                                                              
      7698 BLAKE      MANAGER         7839 01-5月 -81           2850                    30                                                                                                              
      7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0         30                                                                                                              
      7900 JAMES      CLERK           7698 03-12月-81            950                    30                                                                                                              
      已选择 6 行。
      
SQL> --查询部门名称是SALES的员工(方式二)
SQL> select e.*
  2  from emp e,dept d
  3  where e.deptno=d.deptno and d.dname='SALES';
     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO                                                                                                              
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------                                                                                                              
      7499 ALLEN      SALESMAN        7698 20-2月 -81           1600        300         30                                                                                                              
      7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30                                                                                                              
      7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400         30                                                                                                              
      7698 BLAKE      MANAGER         7839 01-5月 -81           2850                    30                                                                                                              
      7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0         30                                                                                                              
      7900 JAMES      CLERK           7698 03-12月-81            950                    30
8、一般不在子查询中排序;但在top-n分析问题中 必须对子查询排序(rownum细节)
1.rownum细节
  • rownum永远按照默认的顺序生成
  • rownum只能使用< <=;不能使用> >=(因为Oracle是一个行式数据库,有了第一行才能有行。不能从中间行号开始,就类似造房子。)
  • rownum 永远从1开始(因为Oracle是一个行式数据库)
2. rownum为什么排序后行号还是不变(临时表)

在这里插入图片描述

3.Oracle的分页图解

在这里插入图片描述

4.找到员工表工资最高的前三名

在这里插入图片描述

SQL> --rownum 行号
SQL> select rownum,empno,ename,sal from emp;

    ROWNUM      EMPNO ENAME             SAL                                                                                                                                                             
---------- ---------- ---------- ----------                                                                                                                                                             
         1       7369 SMITH             800                                                                                                                                                             
         2       7499 ALLEN            1600                                                                                                                                                             
         3       7521 WARD             1250                                                                                                                                                             
         4       7566 JONES            2975                                                                                                                                                             
         5       7654 MARTIN           1250                                                                                                                                                             
         6       7698 BLAKE            2850                                                                                                                                                             
         7       7782 CLARK            2450                                                                                                                                                             
         8       7788 SCOTT            3000                                                                                                                                                             
         9       7839 KING             5000                                                                                                                                                             
        10       7844 TURNER           1500                                                                                                                                                             
        11       7876 ADAMS            1100                                                                                                                                                             

    ROWNUM      EMPNO ENAME             SAL                                                                                                                                                             
---------- ---------- ---------- ----------                                                                                                                                                             
        12       7900 JAMES             950                                                                                                                                                             
        13       7902 FORD             3000                                                                                                                                                             
        14       7934 MILLER           1300                                                                                                                                                             
已选择 14 行。

SQL> select rownum,empno,ename,sal
  2  from emp
  3  where rownum<=3
  4  order by sal desc;

    ROWNUM      EMPNO ENAME             SAL                                                                                                                                                             
---------- ---------- ---------- ----------                                                                                                                                                             
         2       7499 ALLEN            1600                                                                                                                                                             
         3       7521 WARD             1250                                                                                                                                                             
         1       7369 SMITH             800                                                                                                                                                             

SQL> /*
SQL> 关于rownum
SQL> 1、rownum永远按照默认的顺序生成
SQL> 2、rownum只能使用< <=;不能使用> >=
SQL> */
SQL> select rownum,empno,ename,sal from emp order by sal desc;

    ROWNUM      EMPNO ENAME             SAL                                                                                                                                                             
---------- ---------- ---------- ----------                                                                                                                                                             
         9       7839 KING             5000                                                                                                                                                             
        13       7902 FORD             3000                                                                                                                                                             
         8       7788 SCOTT            3000                                                                                                                                                             
         4       7566 JONES            2975                                                                                                                                                             
         6       7698 BLAKE            2850                                                                                                                                                             
         7       7782 CLARK            2450                                                                                                                                                             
         2       7499 ALLEN            1600                                                                                                                                                             
        10       7844 TURNER           1500                                                                                                                                                             
        14       7934 MILLER           1300                                                                                                                                                             
         3       7521 WARD             1250                                                                                                                                                             
         5       7654 MARTIN           1250                                                                                                                                                             

    ROWNUM      EMPNO ENAME             SAL                                                                                                                                                             
---------- ---------- ---------- ----------                                                                                                                                                             
        11       7876 ADAMS            1100                                                                                                                                                             
        12       7900 JAMES             950                                                                                                                                                             
         1       7369 SMITH             800                                                                                                                                                             

已选择 14 行。

SQL> --第一题
SQL> select rownum,empno,ename,sal
  2  from (select * from emp order by sal desc)
  3  where rownum<=3;

    ROWNUM      EMPNO ENAME             SAL                                                                                                                                                             
---------- ---------- ---------- ----------                                                                                                                                                             
         1       7839 KING             5000                                                                                                                                                             
         2       7788 SCOTT            3000                                                                                                                                                             
         3       7902 FORD             3000                                                                                                                                                             

SQL> --2、rownum只能使用< <=;不能使用> >=
SQL> --分页
SQL> select rownum,empno,ename,sal from emp
  2  where  rownum>=5 and rownum<=8;
未选定行

SQL> --rownum 永远从1开始
SQL> select rownum,empno,ename,sal from emp
  2  where  rownum>=5;
未选定行

SQL> ed
已写入 file afiedt.buf

  1  select rownum,empno,ename,sal from emp
  2* where  rownum<=8
SQL> /

    ROWNUM      EMPNO ENAME             SAL                                                                                                                                                             
---------- ---------- ---------- ----------                                                                                                                                                             
         1       7369 SMITH             800                                                                                                                                                             
         2       7499 ALLEN            1600                                                                                                                                                             
         3       7521 WARD             1250                                                                                                                                                             
         4       7566 JONES            2975                                                                                                                                                             
         5       7654 MARTIN           1250                                                                                                                                                             
         6       7698 BLAKE            2850                                                                                                                                                             
         7       7782 CLARK            2450                                                                                                                                                             
         8       7788 SCOTT            3000                                                                                                                                                             

已选择 8 行。

SQL> --Oracle分页,取5到8行的记录
SQL>  select *
  2   from 	(select rownum r,e1.*
  3  	 from (select * from emp order by sal) e1
  4   	 where rownum <=8
  5  	)
  6   where r >=5;

         R      EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO                                                                                                   
---------- ---------- ---------- --------- ---------- -------------- ---------- ---------- ----------                                                                                                   
         5       7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400         30                                                                                                   
         6       7934 MILLER     CLERK           7782 23-1月 -82           1300                    10                                                                                                   
         7       7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0         30                                                                                                   
         8       7499 ALLEN      SALESMAN        7698 20-2月 -81           1600        300         30                                                                                                   



SQL> /*
SQL> 标准表、索引表
SQL> 临时表:1
SQL> 创建方式
SQL> 1. create global temporary table  ****
SQL> 2. 自动:排序
SQL> 特点:当事务或者会话结束的时候,表中的数据自动删除*/
SQL> */
SQL> --创建一张临时表
SQL> create global temporary table temptest1
  2  (tid number ,tname varchar2(20));
表已创建。
SQL> --向表中插入第一条数据
SQL> insert into temptest1 values(1,'Tom');
已创建 1 行。
SQL> --向表中插入第二条数据
SQL> insert into temptest1 values(2,'Mary');
已创建 1 行。
SQL> --查询临时表数据
SQL> select * from temptest1;
       TID TNAME                                                                                                                                                                                        
---------- --------------------                                                                                                                                                                         
         1 Tom                                                                                                                                                                                          
         2 Mary                                                                                                                                                                                         

SQL> --提交事务后,临时表数据会自动删除。
SQL> commit;
提交完成。

SQL> --再次查询临时表数据,数据已经删除了。
SQL> select * from temptest1;
未选定行
9、一般先执行子查询,再执行主查询;但相关子查询例外
1.相关子查询图解

在这里插入图片描述

2.找到员工表中薪水大于本部门平均薪水的员工

在这里插入图片描述

SQL> --使用子查询实现
SQL> select e.empno,e.ename,e.sal,d.avgsal
  2  from emp e,(select deptno,avg(sal) avgsal from emp group by deptno) d
  3  where e.deptno=d.deptno and e.sal>d.avgsal;
     EMPNO ENAME             SAL     AVGSAL                                                                                                                                                             
---------- ---------- ---------- ----------                                                                                                                                                             
      7698 BLAKE            2850 1566.66667                                                                                                                                                             
      7499 ALLEN            1600 1566.66667                                                                                                                                                             
      7902 FORD             3000       2175                                                                                                                                                             
      7788 SCOTT            3000       2175                                                                                                                                                             
      7566 JONES            2975       2175                                                                                                                                                             
      7839 KING             5000 2916.66667                                                                                                                                                             
	  已选择 6 行。

SQL> --使用相关子查询实现
SQL> --相关子查询: 将主查询中的值 作为参数传递给子查询
SQL> select empno,ename,sal,(select avg(sal)  from emp where deptno = e.deptno) avgsal
  2  from emp e
  3  where sal>(select avg(sal)
  4                        from emp
  5                        where deptno = e.deptno);
     EMPNO ENAME             SAL     AVGSAL
---------- ---------- ---------- ----------
      7499 ALLEN            1600 1566.66667
      7698 BLAKE            2850 1566.66667
      7566 JONES            2975       2175
      7788 SCOTT            3000       2175
      7902 FORD             3000       2175
      7839 KING             5000 2916.66667
10、单行子查询只能使用单行操作符;多行子查询只能使用多行操作符
11、子查询中的null
1.单行子查询中的null

在这里插入图片描述

2.多行子查询中的null
SQL> --多行子查询中的null
SQL> --查询不是老板的员工信息
SQL> select *
  2  from emp
  3  where empno not in (select mgr
  4                      from emp);
  未选定行

SQL> --其实在前面已经说过了,not in 关于null值的问题,在not in 中不能有null值,如有有将永远不会成立,也就查询任何不出数据。所以要过滤集合中的null值。
SQL> --SQL> select *
  2  from emp
  3  where empno not in (select mgr
  4                      from emp
  5                      where mgr is not null);
     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 17-12月-80            800                    20
      7499 ALLEN      SALESMAN        7698 20-2月 -81           1600        300         30
      7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30
      7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400         30
      7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0         30
      7876 ADAMS      CLERK           7788 23-5月 -87           1100                    20
      7900 JAMES      CLERK           7698 03-12月-81            950                    30
      7934 MILLER     CLERK           7782 23-1月 -82           1300                    10
      已选择 8 行。

集合运算

在这里插入图片描述

1.并集

在这里插入图片描述

SQL> /*
SQL> 查询10和20号部门的员工
SQL> 1. select * from emp where deptno=10 or deptno=20;
SQL> 2. select * from emp where deptno in (10,20);
SQL> 3. 集合运算
SQL>     select * from emp where deptno=10
SQL>       加上
SQL>     select * from emp where deptno=20
SQL> */
SQL> select *
  2  from emp
  3  where empno not in (select mgr
  4                      from emp
  5                      where mgr is not null);
     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 17-12月-80            800                    20
      7499 ALLEN      SALESMAN        7698 20-2月 -81           1600        300         30
      7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30
      7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400         30
      7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0         30
      7876 ADAMS      CLERK           7788 23-5月 -87           1100                    20
      7900 JAMES      CLERK           7698 03-12月-81            950                    30
      7934 MILLER     CLERK           7782 23-1月 -82           1300                    10
      已选择 8 行。

SQL> --前面已经说过 group by增强,3个sql==gorup by增强
SQL>  select deptno,job,sum(sal) from emp group by rollup(deptno,job);
    DEPTNO JOB         SUM(SAL)                                                                                                                                                                         
---------- --------- ----------                                                                                                                                                                         
        10 CLERK           1300                                                                                                                                                                         
        10 MANAGER         2450                                                                                                                                                                         
        10 PRESIDENT       5000                                                                                                                                                                         
        10                 8750                                                                                                                                                                         
        20 CLERK           1900                                                                                                                                                                         
        20 ANALYST         6000                                                                                                                                                                         
        20 MANAGER         2975                                                                                                                                                                         
        20                10875                                                                                                                                                                         
        30 CLERK            950                                                                                                                                                                         
        30 MANAGER         2850                                                                                                                                                                         
        30 SALESMAN        5600                                                                                                                                                                                                                                                                                                                                               
        30                 9400                                                                                                                                                                         
                          29025                                                                                                                                                                         
        已选择 13 行。

SQL> -使用union连接3个sql==gorup by增强出现sql错误,那就要说说集合运算要注意细节了在第4点。
SQL>  select deptno,job,sum(sal) from emp group by deptno,job
  2   union
  3   select deptno,sum(sal) from emp group by deptno
  4   union
  5   select sum(sal) from emp;
 select deptno,sum(sal) from emp group by deptno
 *
第 3 行出现错误: 
ORA-01789: 查询块具有不正确的结果列数

2.交集

在这里插入图片描述

3.差集

在这里插入图片描述

4.集合运算要注意事项

注意的问题:
1、参与运算的各个集合必须列数相同,且类型一致,在Mysql中集合列数相同,跟数据类型无关
2、采用第一个集合作为最后的表头
3、order by永远在最后查询语句后
4、可以使用括号改变集合执行的顺序

1.参与运算的各个集合必须列数相同 且类型一致

  • 尽量不要使用集合(union)运算查询。(union和group by增强都能完成报表查询,group by增强效率更高。)
--下面3个sql也可以完成group by增强报表统计,但是需要各个集合必须列数相同 且类型一致。
SQL> --同一个部门的不同职位的薪水总和
SQL> select deptno,job,sum(sal)
  2  from emp
  3  group by deptno,job
  4  union
  5  --各部门薪水总和
  6  select deptno,to_char(null),sum(sal)
  7  from emp
  8  group by deptno
  9  union
 10  --员工薪水总和
 11  select to_number(null),to_char(null),sum(sal)
 12  from emp;
    DEPTNO JOB         SUM(SAL)
---------- --------- ----------
        10 CLERK           1300
        10 MANAGER         2450
        10 PRESIDENT       5000
        10                 8750
        20 ANALYST         6000
        20 CLERK           1900
        20 MANAGER         2975
        20                10875
        30 CLERK            950
        30 MANAGER         2850
        30 SALESMAN        5600
        30                 9400
                          29025
		已选择 13 行。
		
SQL> --break on deptno skip 2
SQL> --现在有个问题就是, union 和 gorup by 都能完成报表统计那使用谁呢?
SQL> --开启显示SQL 执行的时间 
SQL> set timing on
SQL> select deptno,job,sum(sal) from emp group by rollup(deptno,job);
    DEPTNO JOB         SUM(SAL)
---------- --------- ----------
        10 CLERK           1300
        10 MANAGER         2450
        10 PRESIDENT       5000
        10                 8750
        20 CLERK           1900
        20 ANALYST         6000
        20 MANAGER         2975
        20                10875
        30 CLERK            950
        30 MANAGER         2850
        30 SALESMAN        5600
        30                 9400
                          29025
已选择 13 行。
已用时间:  00: 00: 00.02

SQL> --同一个部门的不同职位的薪水总和
SQL> select deptno,job,sum(sal)
  2  from emp
  3  group by deptno,job
  4  union
  5  --各部门薪水总和
  6  select deptno,to_char(null),sum(sal)
  7  from emp
  8  group by deptno
  9  union
 10  --员工薪水总和
 11  select to_number(null),to_char(null),sum(sal)
 12  from emp;
    DEPTNO JOB         SUM(SAL)
---------- --------- ----------
        10 CLERK           1300
        10 MANAGER         2450
        10 PRESIDENT       5000
        10                 8750
        20 ANALYST         6000
        20 CLERK           1900
        20 MANAGER         2975
        20                10875
        30 CLERK            950
        30 MANAGER         2850
        30 SALESMAN        5600
        30                 9400
                          29025
已选择 13 行。
已用时间:  00: 00: 00.07

SQL> --通过执行时间使用group by效率更高
SQL> --关闭显示SQL 执行的时间
SQL> set timing off

2.order by永远在最后查询语句后

  • 集合运算在oracle中order by永远在最后查询语句后
  • 集合运算在Mysql中order by不能直接使用,需要对查询语句使用括号才行,若要orderby生效必须搭配limit,limit使用限定的最大数即可

Mysql集合运算示例
在这里插入图片描述
Oracle示例

SQL> --集合运算order by不出现在查询最后,会出现语法报错。
SQL> --同一个部门的不同职位的薪水总和
SQL> select deptno,job,sum(sal)
  2  from emp
  3  group by deptno,job order by deptno desc
  4  union
  5  --各部门薪水总和
  6  select deptno,to_char(null),sum(sal)
  7  from emp
  8  group by deptno
  9  union
 10  --员工薪水总和
 11  select to_number(null),to_char(null),sum(sal)
 12  from emp;
union
*
第 4 行出现错误:
ORA-00933: SQL 命令未正确结束

SQL> --集合运算order by永远在最后查询语句后。
SQL> --同一个部门的不同职位的薪水总和
SQL> select deptno,job,sum(sal)
  2  from emp
  3  group by deptno,job
  4  union
  5  --各部门薪水总和
  6  select deptno,to_char(null),sum(sal)
  7  from emp
  8  group by deptno
  9  union
 10  --员工薪水总和
 11  select to_number(null),to_char(null),sum(sal)
 12  from emp order by deptno desc;
    DEPTNO JOB         SUM(SAL)
---------- --------- ----------
                          29025
        30 CLERK            950
        30 MANAGER         2850
        30 SALESMAN        5600
        30                 9400
        20 ANALYST         6000
        20 CLERK           1900
        20 MANAGER         2975
        20                10875
        10 CLERK           1300
        10 MANAGER         2450
        10 PRESIDENT       5000
        10                 8750
	    已选择 13 行。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值