天天看点

Oracle子查询

sql> --问题:要查询工资比scott高的员工信息

sql> --1. 查询scott的工资

sql> select sal from emp where ename='scott';

       sal                                                                     

----------                                                                     

      3000                                                                     

sql> --2.  查询比3000 高的

sql> select *

  2  from emp

  3  where sal >3000;

     empno ename      job              mgr hiredate              sal       comm

---------- ---------- --------- ---------- -------------- ---------- ----------

    deptno                                                                     

      7839 king       president            17-11月-81           5000           

        10                                                                     

sql> set linesize 120

sql> col sal for 9999

sql> /

     empno ename      job              mgr hiredate         sal       comm     deptno                                  

---------- ---------- --------- ---------- -------------- ----- ---------- ----------                                  

      7839 king       president            17-11月-81      5000                    10                                  

sql> --子查询解决上面的问题

  3  where sal > ( select sal

  4                from emp

  5                where ename='scott');

sql> --书写子查询的注意事项:

sql> /*

sql> 1. 将子查询放入括号中

sql> 2. 将子查询往右放

sql> 3. 一般子查询不使用order by 但是在top-n分析和分页中需要

sql> 4. group by后,不能使用子查询

sql> 5. select, from, where后面可以使用

sql> 6. 主查询和子查询可以不是一张表,只要子查询返回的结果主查询可以使用 就ok

sql> 7. 可以将子查询视为一张新表.

sql> */

sql> --在from后面使用子查询

sql> --查询部门名称为sales的员工信息

sql> select e.empno,e.ename

  2  from emp e,dept d

  3  where e.deptno=d.deptno

  4  and d.dname='sales';

     empno ename                                                                                                       

---------- ----------                                                                                                  

      7499 allen                                                                                                       

      7521 ward                                                                                                        

      7654 martin                                                                                                      

      7698 blake                                                                                                       

      7844 turner                                                                                                      

      7900 james                                                                                                       

已选择6行。

  3  where deptno= (select deptno

  4                 from dept

  5                 where dname ='sales');

      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                                  

sql> -- 查询员工的名字和工资

sql> select ename,sal

  2  from emp;

ename        sal                                                                                                       

---------- -----                                                                                                       

smith        800                                                                                                       

allen       1600                                                                                                       

ward        1250                                                                                                       

jones       2975                                                                                                       

martin      1250                                                                                                       

blake       2850                                                                                                       

clark       2450                                                                                                       

scott       3000                                                                                                       

king        5000                                                                                                       

turner      1500                                                                                                       

adams       1100                                                                                                       

james        950                                                                                                       

ford        3000                                                                                                       

miller      1300                                                                                                       

已选择14行。

  2  from (select ename,sal)

  3  ;

from (select ename,sal)

                      *

第 2 行出现错误:

ora-00923: 未找到要求的 from 关键字

sql> ed

已写入 file afiedt.buf

  1  select *

  2* from (select ename,sal from emp)

sql> --select后面跟子查询

sql> select (select dname from deptno where deptno=10),ename

select (select dname from deptno where deptno=10),ename

                          *

第 1 行出现错误:

ora-00942: 表或视图不存在

sql> select (select dname from dept where deptno=10),ename

(selectdnamefr ename                                                                                                   

-------------- ----------                                                                                              

accounting     smith                                                                                                   

accounting     allen                                                                                                   

accounting     ward                                                                                                    

accounting     jones                                                                                                   

accounting     martin                                                                                                  

accounting     blake                                                                                                   

accounting     clark                                                                                                   

accounting     scott                                                                                                   

accounting     king                                                                                                    

accounting     turner                                                                                                  

accounting     adams                                                                                                   

accounting     james                                                                                                   

accounting     ford                                                                                                    

accounting     miller                                                                                                  

sql> --可以将子查询视为新表

sql> select e.ename,e.sal

  2  from (select ename,sal from emp) e;

sql> --8.可以有多个子查询

sql> --多行子查询

sql> --查询部门名称为sales和accounting的员工信息

  3  where deptno=(select deptno

  4                from dept

  5                where dname='sales' or dname='accouting');

  3  where deptno in (select deptno

  5*               where dname='sales' or dname='accouting')

sql> --查询工资最低的员工信息

  3  where sal = (select min(sal)

  4               from emp);

      7369 smith      clerk           7902 17-12月-80       800                    20                                  

  3  where sal = ( select min(sal)

  5                group by deptno);

where sal = ( select min(sal)

              *

第 3 行出现错误:

ora-01427: 单行子查询返回多个行

sql> -- 关于null

sql> host cls

sql> --查询不是经理的员工的信息

sql> select * from emp;

      7566 jones      manager         7839 02-4月 -81      2975                    20                                  

      7782 clark      manager         7839 09-6月 -81      2450                    10                                  

      7788 scott      analyst         7566 13-7月 -87      3000                    20                                  

      7876 adams      clerk           7788 13-7月 -87      1100                    20                                  

      7902 ford       analyst         7566 03-12月-81      3000                    20                                  

      7934 miller     clerk           7782 23-1月 -82      1300                    10                                  

  3  where empno not in  (select mgr  from emp)

  4  ;

未选定行

  3* where empno not in  (select mgr  from emp where mgr is not null)

已选择8行。

sql> --如果子查询中,包含null,类似表达式,会导致整个集合为null

sql> -any的使用

sp2-0042: 未知命令 "-any的使用" - 其余行忽略。

sql> --any的使用

sql> --问题: 查询工资比10号部门员工中任意一个低的员工信息

  3  where sal < any (select sal from emp where deptno=10);

已选择13行。

sql> --等同于

  3  where sal < (select max(sal) from emp where deptno=10);

sql> --all的使用

sql> --查询工资比10号部门都要低的员工信息

  3  where sal < all (select sal from emp where deptno=10);

  3* where sal <  (select min(sal) from emp where deptno=10)

sql> spool off

sql> --课堂练习

sql> --第一题: 伪列

sql> -- rownum:行号

sql> select rownum,empno,ename from emp;

    rownum      empno ename                                                                                            

---------- ---------- ----------                                                                                       

         1       7369 smith                                                                                            

         2       7499 allen                                                                                            

         3       7521 ward                                                                                             

         4       7566 jones                                                                                            

         5       7654 martin                                                                                           

         6       7698 blake                                                                                            

         7       7782 clark                                                                                            

         8       7788 scott                                                                                            

         9       7839 king                                                                                             

        10       7844 turner                                                                                           

        11       7876 adams                                                                                            

        12       7900 james                                                                                            

        13       7902 ford                                                                                             

        14       7934 miller                                                                                           

sql> --关于rownum的注意事项:

sql> --1. rownum一旦生成就不变

sql> --2. rownum只能使用<=,不能使用>=

sql> select rownum,ename

  3  order by sal;

    rownum ename                                                                                                       

         1 smith                                                                                                       

        12 james                                                                                                       

        11 adams                                                                                                       

         3 ward                                                                                                        

         5 martin                                                                                                      

        14 miller                                                                                                      

        10 turner                                                                                                      

         2 allen                                                                                                       

         7 clark                                                                                                       

         6 blake                                                                                                       

         4 jones                                                                                                       

         8 scott                                                                                                       

        13 ford                                                                                                        

         9 king                                                                                                        

  3  where rownum<=3

  4  orber by sal desc;

orber by sal desc

*

第 4 行出现错误:

ora-00933: sql 命令未正确结束

  4* order by sal desc

sql> select rownum,ename,sal

  3  where rownum<3;

    rownum ename        sal                                                                                            

---------- ---------- -----                                                                                            

         1 smith        800                                                                                            

         2 allen       1600                                                                                            

  1  select rownum,ename,sal

  3* where rownum>3

sql> --关于rownum的生成机制:必须从依次取出,然后付到记录上

sql> --第二题:将子查询结果集视为新表

sql> --第三题:

sql> select hiredate from emp;

hiredate                                                                                                               

--------------                                                                                                         

17-12月-80                                                                                                             

20-2月 -81                                                                                                             

22-2月 -81                                                                                                             

02-4月 -81                                                                                                             

28-9月 -81                                                                                                             

01-5月 -81                                                                                                             

09-6月 -81                                                                                                             

13-7月 -87                                                                                                             

17-11月-81                                                                                                             

08-9月 -81                                                                                                             

03-12月-81                                                                                                             

23-1月 -82                                                                                                             

sql> --假设:我们已知道入职的年份有: 80 81 82 87

sql> -- 第一题

  2  from  (select * from emp order by sal desc)

  3  where rownum<=3;

         1 king        5000                                                                                            

         2 scott       3000                                                                                            

         3 ford        3000                                                                                            

  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> select e.empno,e.ename,e.sal,d.avgsal

  2  from emp e,(select deptno, avg(sal) avgsal from emp group by deptno) d

  4  and e.sal>d.avgsal;

     empno ename        sal     avgsal                                                                                 

---------- ---------- ----- ----------                                                                                 

      7499 allen       1600 1566.66667                                                                                 

      7566 jones       2975       2175                                                                                 

      7698 blake       2850 1566.66667                                                                                 

      7788 scott       3000       2175                                                                                 

      7839 king        5000 2916.66667                                                                                 

      7902 ford        3000       2175                                                                                 

sql> --第三题

sql> select to_char(hiredate,'yyyy') from emp;

to_c                                                                                                                   

----                                                                                                                   

1980                                                                                                                   

1981                                                                                                                   

1987                                                                                                                   

1982                                                                                                                   

sql> select count(*) total,

  2         sum(decode(to_char(hiredate,'yyyy'),'1980',1,0)) "1980"

  3         sum(decode(to_char(hiredate,'yyyy'),'1981',1,0)) "1981"

  4         sum(decode(to_char(hiredate,'yyyy'),'1982',1,0)) "1982"

  5         sum(decode(to_char(hiredate,'yyyy'),'1987',1,0)) "1987"

  6  from emp;

       sum(decode(to_char(hiredate,'yyyy'),'1981',1,0)) "1981"

       *

  2         sum(decode(to_char(hiredate,'yyyy'),'1980',1,0)) "1980",

  3         sum(decode(to_char(hiredate,'yyyy'),'1981',1,0)) "1981",

  4         sum(decode(to_char(hiredate,'yyyy'),'1982',1,0)) "1982",

     total       1980       1981       1982       1987                                                                 

---------- ---------- ---------- ---------- ----------                                                                 

        14          1         10          1          2