• oracle实验20:子查询


    子查询

    语法:

    SELECT 查询列
    FROM表名
    WHERE 列名操作符
         (SELECT查询列
          FROM表名);

    -括号内的查询叫做子查询(Subquery)或者内部查询(Inner Query),
    -外面的查询叫做主查询(Main query)或外部查询(Outer query)。

    实验20:子查询

    谁的工资最多?

    1.查最大工资值
    SQL> select max(sal) from emp;

      MAX(SAL)
    ----------
          5000

    2.找到最大工资值的人
    SQL> select ename from emp where sal=5000;

    ENAME
    ----------
    KING

    将两个语句写在一起
    SQL> select ename from emp where sal=(select max(sal) from emp);

    ENAME
    ----------
    KING                                                      

    简单子查询

    • 先于主查询执行;
    • 主查询调用了子查询的结果;
    • 注意列的个数和类型要匹配;
    • 子查询返回多行要用多行关系运算操作;
    • 子查询需要写在括号中;
    • 子查询需要写在运算符的右端;
    • 子查询可以写在WHERE,HAVING,FROM子句中;
    • 子查询中通常不写ORDER BY子句。

    单行子查询

    子查询返回的记录有且只有一条。单行子查询要求使用单行操作符。
     即:<、>、>=、<=、=、<>

    查询工资总和高于10号部门工资总和的部门

    SQL>  select deptno,sum(sal)
          from emp
          group by deptno
         having sum(sal)>
         (select sum(sal) from emp where deptno=10);

        DEPTNO   SUM(SAL)                                                          
    ---------- ----------                                                          
            30       9400                                                          

     

    多行多列子查询

    多行子查询,子查询返回记录的条数可以是一条或多条。多行子查询需要使用多行操作符。常用的多行操作符包括:
    –IN
    –ANY
    –ALL

    IN操作符 判断是否与子查询的任意一个返回值相同。返回的结果可以是一条或多条。

    查询每个部门的最大工资

    SQL>  select deptno,ename,sal from emp
          where (deptno,sal) in (select deptno,max(sal) from emp group by deptno);

        DEPTNO ENAME             SAL                                               
    ---------- ---------- ----------                                               
            30 BLAKE            2850                                               
            20 FORD             3000                                               
            10 KING             5000                                               

     

    ANY 表示任意的。

    SQL> select ename,sal from emp where sal<any(1000,2000);

    ENAME             SAL                                                          
    ---------- ----------                                                          
    SMITH             800                                                          
    ALLEN            1600                                                          
    WARD             1250                                                          
    MARTIN           1250                                                          
    TURNER           1500                                                          
    JAMES             950                                                          
    MILLER           1300                                                          

    已选择7行。

    小于2000就可以。

     

    ALL 表示所有的。

    SQL> select ename,sal from emp where sal<all(1000,2000);

    ENAME             SAL                                                          
    ---------- ----------                                                          
    SMITH             800                                                          
    JAMES             950                                                          

    必须小于1000。

    小于any,小于最大值;大于any,大于最小值。
    小于all,小于最小值;大于all,大于最大值。

    SQL> select avg(sal) from emp group by deptno;

      AVG(SAL)
    ----------
          1567
    2259.33333
    2916.66667

    SQL> select ename,sal,deptno from emp
             where sal<any(select avg(sal) from emp group by deptno);

    ENAME             SAL     DEPTNO
    ---------- ---------- ----------
    SMITH             801         20
    JAMES             950         30
    WARD             1250         30
    MARTIN           1250         30
    MILLER           1300         10
    TURNER           1501         30
    ALLEN            1601         30
    CLARK            2450         10
    BLAKE            2850         30

    已选择9行。

    SQL>  select ename,sal,deptno from emp
              where sal>any(select avg(sal) from emp group by deptno);

    ENAME             SAL     DEPTNO
    ---------- ---------- ----------
    KING             5000         10
    FORD             3002         20
    JONES            2975         20
    BLAKE            2850         30
    CLARK            2450         10
    ALLEN            1601         30

    已选择6行。
     
    SQL> select ename,sal,deptno from emp
            where sal<all(select avg(sal) from emp group by deptno)

    ENAME             SAL     DEPTNO
    ---------- ---------- ----------
    SMITH             801         20
    WARD             1250         30
    MARTIN           1250         30
    TURNER           1501         30
    JAMES             950         30
    MILLER           1300         10

    已选择6行。

    FROM语句中子查询

    找出比本部门工资高的员工

    SQL> select ename,e.deptno,sal,asal from emp e,
         (select deptno,avg(sal) asal from emp group by deptno) a
         where e.deptno=a.deptno and sal>asal;

    ENAME          DEPTNO        SAL       ASAL                                    
    ---------- ---------- ---------- ----------                                    
    ALLEN              30       1600 1566.66667                                    
    JONES              20       2975 2258.33333                                    
    BLAKE              30       2850 1566.66667                                    
    KING               10       5000 2916.66667                                    
    FORD               20       3000 2258.33333                                    

    a为视图,使用别名asal是因为表达式不能当列的名称,别名的本质是非法的合法化。

    子查询中空值问题

    SQL> SELECT a.ename, a.sal FROM emp a WHERE a.empno NOT IN(SELECT b.mgr FROM emp b);

    未选定行

    出现这种情况的原因有两个:

    -子查询中返回值中包含有空值;
    -NOT IN操作符对空值不忽略。

    NOT IN操作符相当于<> ALL,即除了列表值的所有值,就包括了空值NULL,结果即为空。

    相互关联的子查询

    相关子查询中,内部查询需引用外部查询的列,进行交互判断。相关子查询的执行方式是一行行操作。外部查询每执行一行操作,内部查询都要执行一次。

    SQL>  select ename,sal,deptno
          from emp o
          where sal>(select avg(sal) from emp where deptno=o.deptno);

    ENAME             SAL     DEPTNO                                               
    ---------- ---------- ----------                                               
    ALLEN            1600         30                                               
    JONES            2975         20                                               
    BLAKE            2850         30                                               
    KING             5000         10                                               
    FORD             3000         20                                               

    先运行主查询,得到第一行,将DEPTNO传入到子查询,由于查询求出avg(sal),再判定主查询的行是否符合查询的条件。
    执行计划是将子查询看作视图的关联,这叫做sql的自动改写。

    EXISTS和NOT EXISTS操作符

    相关子查询还可使用EXISTS和NOT EXISTS操作符。

    EXISTS判断存在与否。具体操作如下:

    –子查询中如果有记录找到,子查询语句不会继续执行,返回值为TRUE;
    –子查询中如果到表的末尾也没有记录找到,返回值为FALSE。

    EXISTS子查询并没有确切记录返回,只判断是否有记录。而且只要找到相关记录,子查询就不需要再执行,然后再进行下面的操作。这样大大提高了语句的执行效率。

    NOT EXISTS正好相反,判断子查询是否没有返回值。

    -如果没有返回值,表达式为真,
    -如果找到一条返回值,则为假。

    NOT EXISTS操作符因为运算方法与NOT IN不同,只会返回TRUE或FALSE,不会返回空值,所以不需要考虑子查询去除空值的问题。

    SQL>  select ename,empno,mgr from emp o where exists(select 1 from emp where mgr=o.empno);

    ENAME           EMPNO        MGR                                               
    ---------- ---------- ----------                                               
    JONES            7566       7839                                               
    BLAKE            7698       7839                                               
    CLARK            7782       7839                                               
    KING             7839                                                          
    FORD             7902       7566                                               


    练习

    1.列出没有下级的员工。
    答案: select ename,empno,mgr from emp o where not exists(select 1 from emp where mgr=o.empno);

    2.每个部门工资最少的员工。

    答案: select deptno, ename,sal
         from emp
         where (deptno,sal) in (select deptno,min(sal) from emp group by deptno);

     3.所有比平均工资高的员工。

    返回目录  http://www.cnblogs.com/downpour/p/3155689.html

  • 相关阅读:
    Decimal、 Float、 Double 使用
    jdk1.7的collections.sort(List list)排序问题
    $watch、$digest、$apply
    BeanNameViewResolver
    This system is not registered with RHN
    JNI字段描述符-Java Native Interface Field Descriptors
    服务器端cs文件
    ASP.NET基础(一)
    Android开发日记(七)
    登陆 注册
  • 原文地址:https://www.cnblogs.com/downpour/p/3159229.html
Copyright © 2020-2023  润新知