oracle 子查询

查询工资比SCOTT高的员工信息

SELECT * FROM EMP WHERE SAL > (SELECT SAL FROM EMP WHERE ENAME='SCOTT');

     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM
---------- ---------- --------- ---------- -------------- ---------- ----------
    DEPTNO
----------
      7839 KING       PRESIDENT            17-11月-81           5000
        10

子查询需要注意的10个问题:

子查询语法中的小括号问题

SELECT *
  2  FROM EMP
  3  WHERE SAL > SELECT SAL
  4          FROM EMP
  5*                      WHERE ENAME='SCOTT'
SQL> /
WHERE SAL > SELECT SAL--子查询没有带括号
            *
第 3 行出现错误:
ORA-00936: 缺失表达式

子查询的书写风格问题

该换行的换行,该缩进的缩进。

可以使用子查询的位置:WHERE,SELECT,HAVING,FROM

SELECT EMPNO,ENAME,SAL,(SELECT JOB FROM EMP WHERE EMPNO=7839) 第四列
  2  FROM EMP;--SELECT 语句只能使用单行子查询,子查询返回单个结果为单行子查询,多个结果为多行子查询
SELECT DEPTNO,AVG(SAL)
  2  FROM EMP
  3  GROUP BY DEPTNO
  4  HAVING AVG(SAL) > (SELECT MAX(SAL)
  5                     FROM EMP
  6                     WHERE DEPTNO=30);

    DEPTNO   AVG(SAL)
---------- ----------
        10 2916.66667
SELECT * FROM (SELECT EMPNO,ENAME,SAL FROM EMP);--ORACLE中很多问题都是通过FROM子查询解决

     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

     EMPNO ENAME             SAL
---------- ---------- ----------
      7900 JAMES             950
      7902 FORD             3000
      7934 MILLER           1300

不可以使用子查询的位置

GROUP BY

SELECT AVG(SAL)
  2  FROM EMP
  3  GROUP BY (SELECT DEPTNO
  4             FROM EMP);
GROUP BY (SELECT DEPTNO
          *
第 3 行出现错误:
ORA-22818: 这里不允许出现子查询表达式

FROM后面的子查询(*)

查询员工信息:员工号,姓名,月薪

SELECT * FROM (SELECT EMPNO,ENAME,SAL FROM EMP);

查询员工信息:员工号,姓名,月薪,年薪

SELECT * FROM (SELECT EMPNO,ENAME,SAL,SAL*12 ANNSAL FROM EMP);

     EMPNO ENAME             SAL     ANNSAL
---------- ---------- ---------- ----------
      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

     EMPNO ENAME             SAL     ANNSAL
---------- ---------- ---------- ----------
      7900 JAMES             950      11400
      7902 FORD             3000      36000
      7934 MILLER           1300      15600

主查询和子查询可以不是同一张表

查询部门名称是SALES的员工信息

SELECT *
  2  FROM EMP
  3  WHERE DEPTNO=(SELECT DEPTNO
  4               FROM DEPT
  5                     WHERE DNAME='SALES');
SELECT E.*
FROM EMP E,DEPT D
WHERE  E.DEPTNO=D.DEPTNO AND D.DNAME='SALES';

理论上,多表查询比较好,实际情况子查询可能比多表查询好,需要考虑多表查询产生的笛卡尔集,具体用哪种根据实际情况而定。

一般不在子查询中使用排序;但在TOP N分析问题中,必须对子查询进行排序。

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

SELECT ROWNUM,EMPNO,ENAME,SAL
FROM (SELECT * FROM EMP ORDER BY SAL DESC)
WHERE  ROWNUM<=3;--ROWNUM 行号 伪列,行号永远按默认的顺序生成,行号只能使用<,<=;不能使用>,>=.

主查询和子查询的执行顺序

一般先执行主查询再执行子查询;但相关查询例外。

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

 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
      7566 JONES            2975       2175
      7698 BLAKE            2850 1566.66667
      7788 SCOTT            3000       2175
      7839 KING             5000 2916.66667
      7902 FORD             3000       2175

单行子查询和多行子查询

单行子查询只能使用单行操作符,多行子查询只能使用多行操作符。

查询员工信息:要求职位与7566员工一样,同时薪水大于7782员工的薪水

 SELECT *
  2  FROM EMP
  3  WHERE JOB = (SELECT JOB FROM EMP WHERE EMPNO=7566) AND
  4    SAL > (SELECT SAL FROM EMP WHERE EMPNO=7782);

     EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM
---------- ---------- --------- ---------- -------------- ---------- ----------
    DEPTNO
----------
      7566 JONES      MANAGER         7839 02-4月 -81           2975
        20

      7698 BLAKE      MANAGER         7839 01-5月 -81           2850

查询工资最低的员工信息

SELECT *
FROM EMP 
WHERE SAL = (SELECT MIN(SAL) FROM EMP);

查询最低工资大于20号部门的最低工资的部门号和最低工资

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

多行操作符IN

查询部门名称是SALES和ACCOUNTING的员工信息

SELECT *
  2  FROM EMP
  3  WHERE DEPTNO IN (SELECT DEPTNO FROM DEPT WHERE DNAME='SALES' OR DNAME='ACCOUNTING');
SELECT E.*
FROM EMP E, DEPT D
WHERE E.DEPTNO=D.DEPTNO AND (D.DNAME='SALES' OR D.DNAME='ACCOUNTING');

多行操作符ANY

查询工资比30号部门任意一个员工工资高的员工信息

SELECT *
FROM EMP 
WHERE SAL > ANY (SELECT SAL FROM EMP WHERE DEPTNO = 30);

SELECT *
FROM EMP 
WHERE SAL > (SELECT MIN(SAL) FROM EMP WHERE DEPTNO = 30);

多行操作符ALL

查询工资比30号部门所有员工工资高的员工信息

SELECT *
FROM EMP 
WHERE SAL > ALL (SELECT SAL FROM EMP WHERE DEPTNO = 30);
SELECT *
FROM EMP 
WHERE SAL > (SELECT MAX(SAL) FROM EMP WHERE DEPTNO = 30);

子查询中的NULL值问题

单行子查询

SELECT ENAME,JOB
  2  FROM EMP
  3  WHERE JOB = (SELECT JOB
  4  FROM EMP
  5  WHERE ENAME = 'TOM');

未选定行--子查询不返回任何行。

多行子查询

查询不是老板的员工(只要多行子查询有空值,不要用NOT IN,可以用IN)

SELECT *
FROM EMP 
WHERE EMPNO NOT IN (SELECT MGR 
					FROM EMP
					WHERE MGR IS NOT NULL);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值