oracle9i學習筆記之十六 高級子查詢

 1.子查詢回顧
 
  SELECT   select_list
  FROM     table
  WHERE    expr operator(SELECT  select_list
                         FROM    table);

例1:查詢emp表,顯示薪水大於平均薪水的僱員信息

     SELECT *
     FROM   emp
     WHERE  sal>(SELECT AVG(sal)
                 FROM   emp);

例2:顯示僱員的細節信息,要求這些僱員的經理和部門與僱員號爲7521或7698是相同的,但不包括empno爲7521或7698的僱員信息
   
   SELECT *
   FROM   emp
   WHERE  (mgr,deptno) IN(SELECT mgr,deptno
                          FROM   emp
                          WHERE  empno IN(7521,7698))
   AND    empno NOT IN(7521,7698);

例3:顯示與薪水大於2900元的僱員相同部門、相同工作類型的其他僱員信息
     
     SELECT *
     FROM   emp
     WHERE  (deptno,job) IN(SELECT deptno,job
                            FROM   emp
                            WHERE  sal>2900)
     AND    sal<=2900;

例4:顯示與薪水大於2900元的僱員相同部門、相同工作類型的其他僱員信息(在FROM子句中使用子查詢)

    SELECT *
    FROM   emp e,(SELECT deptno,job,sal
                  FROM   emp
                  WHERE  sal>2900) s
    WHERE e.deptno=s.deptno
    AND   e.job=s.job
    AND   e.sal!=s.sal;

2.相關子查詢
1)相關子查詢是一種讀表中每一行並且依靠相關數據比較每行的值的方法,相關子查詢被用於row-by-row處理。對外查詢的每一行,每個子查詢被執行一次。
2)嵌套子查詢與相關子查詢
  (1)嵌套子查詢的執行
     -內查詢首先執行並且查找值
     -外查詢用內查詢的值執行一次
  (2)相關子查詢的執行
     -用外查詢取得候選行
     -用候選行的值執行內查詢
     -用來自內查詢的值確認或取消候選行
     -重複直到無剩餘的候選行  

   SELECT column1,column2,...
   FROM   table1 outer
   WHERE  column1 operator(SELECT column1,column2
                           FROM   table2
                           WHERE  expr1=outer.expr2)                    

例:找出所有的僱員,他們掙的薪水高於該部門的平均薪水

    SELECT ename,deptno,sal
    FROM   emp outer
    WHERE  sal>(SELECT AVG(sal)
                FROM   emp
                WHERE  deptno=outer.deptno);
結果:
      ENAME  DEPTNO  SAL 
      ALLEN    30    1600 
      JONES    20    2975 
      BLAKE    30    2850 
      SCOTT    20    3000 
      KING     10    5000 
      FORD     20    3000 
      小王     10    3000 


3.EXISTS操作
  EXISTS操作對在子查詢的結果集中存在的行進行檢驗:
  1)如果一個子查詢行值被找到:
    -在內查詢中的搜索不再繼續
    -條件被標記爲TRUE
  2)如果一個子查詢行值未找到
    -條件被標記爲FALSE
    -在內查詢中的搜索繼續

例:查找至少有一個僱員的經理信息
   
    SELECT *
    FROM   emp outer
    WHERE  EXISTS(SELECT 'X'
                  FROM   emp
                  WHERE  mgr=outer.empno);
結果:
     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         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 
     7902   FORD   ANALYST   7566  03-12月-81  3000         20 


4.NOT EXISTS操作
例:查找部門編號不在僱員表中的部門信息

   SELECT *
   FROM   dept
   WHERE  NOT EXISTS(SELECT *
                     FROM   emp
                     WHERE  emp.deptno=dept.deptno);
  

5.相關UPDATE
  -用一個相關子查詢來更新一個表中的行,該表中的行基於另一個表中的行

  UPDATE table1 alias1
  SET    column=(SELECT expression
                 FROM   table2 alias2
                 WHERE  alias1.column=alias2.column);

例:1.在僱員表中增加部門名稱列
  
     ALTER TABLE emp
     ADD   (dname VARCHAR2(14));

   2.使用部門表中的部門名稱更新僱員表中的部門名稱

     UPDATE emp e
     SET    dname=(SELECT dname
                   FROM   dept d
                   WHERE  e.deptno=d.deptno);

6.相關delete
  -用一個相關子查詢來刪除一個表中的行,該表中的行基於另一個表中的行
 
  DELETE FROM table1 alias1
  WHERE  column operator(SELECT expression
                         FROM   table2 alias2
                         WHERE  alias1.column=alias2.column);

例:用一個相關子查詢刪除emp表中的數據,被刪除的數據是emp表和job_history表中有相同empno列值的數據
   
    DELETE FROM emp e
    WHERE  empno IN (SELECT empno
                     FROM   job_history
                     WHERE  empno=e.empno);

7.WITH子句
1)當一個查詢塊在一個複雜的查詢中出現多次時,使用WITH子句,能夠用在SELECT語句中使用相同查詢塊
2)WITH子句取回查詢塊的結果,並且將它存在用戶的臨時表空間中
3)WITH子句可以改善性能 

例:用WITH子句,寫一個查詢來顯示部門名稱和該部門的合計薪水,那些人的合計薪水高於各部門的平均薪水

   WITH
   dept_costs AS(
       SELECT   d.dname,SUM(e.sal) AS dept_total
       FROM     emp e,dept d
       WHERE    e.deptno=d.deptno
       GROUP BY d.dname),
   avg_costs AS(
       SELECT SUM(dept_total)/COUNT(*) AS dept_avg
       FROM   dept_costs)
   SELECT *
   FROM   dept_costs
   WHERE  dept_total>(SELECT dept_avg
                      FROM   avg_costs)
   ORDER BY dname;
結果:
      DNAME        DEPT_TOTAL 
      ACCOUNTING   11750 
      RESEARCH     14075 

練習
1.顯示變換過至少兩次工作的僱員的詳細情況(emp和job_history)

 

2.寫一個子查詢顯示任何一個其部門號和薪水都與任何掙佣金的僱員的部門號和薪水相匹配的僱員的名字、部門號和薪水

  SELECT ename,deptno,sal
  FROM   emp
  WHERE  (deptno,sal) IN(SELECT deptno,sal
                         FROM   emp
                         WHERE  comm IS NOT NULL);

3.顯示任何其薪水和佣金與任何位於loc爲CHICAGO的僱員薪水和佣金相匹配的僱員的名字、部門名和薪水
 
  SELECT ename, dname, sal
  FROM emp e, dept d
  WHERE e.deptno = d.deptno
  AND (sal, NVL(comm,0)) IN (SELECT sal, NVL(comm,0)
        FROM emp e, dept d
        WHERE e.deptno = d.deptno
        AND d.loc = 'CHICAGO');

4.創建一個查詢來顯示所有其薪水和佣金與SCOTT相同的僱員的名字、受僱日期和薪水(不顯示SCOTT的信息)
 
  SELECT ename,hiredate,sal
  FROM   emp
  WHERE  (sal,NVL(comm,0)) IN (SELECT sal,NVL(comm,0)
                                 FROM emp
                                WHERE ename='SCOTT')
  AND   ename!='SCOTT';


5.創建一個查詢來顯示那些所掙薪水高於所有經理(job='MANAGER')的僱員的名字、工作崗位和薪水。依據薪水從最高到最低排序結果集

  SELECT ename,job,sal
  FROM   emp
  WHERE  sal>ALL (SELECT sal
                  FROM   emp
                  WHERE  job='MANAGER')
  ORDER BY sal DESC;

6.顯示那些住在城市名字以N開頭的城市的僱員的ID、名字和部門號

  SELECT empno,ename,deptno
  FROM   emp
  WHERE  deptno IN(SELECT deptno
                   FROM   dept
                   WHERE  loc LIKE 'N%');


7.寫一個查詢來查找所有其薪水多於他所在部門的平均薪水的僱員,顯示名字、部門號和部門的平均薪水,按平均薪水排序

  SELECT ename,e.deptno,sal,a.avg
  FROM   emp e,(SELECT   deptno,AVG(sal) avg
                  FROM    emp
                 GROUP BY deptno) a
  WHERE e.deptno=a.deptno
  AND   e.sal>a.avg
  ORDER BY a.avg;

8.寫一個查詢顯示所掙薪水低於他們所在的部門平均薪水的僱員名

  SELECT ename
 FROM emp outer
 WHERE sal< (SELECT AVG(sal)
      FROM emp inner
             WHERE deptno = outer.deptno);
  或:
  SELECT ename
         FROM emp outer
  WHERE outer.sal< (SELECT AVG(inner.sal)
      FROM   emp inner
             WHERE  inner.deptno = outer.deptno);

9.查找所有不是管理人員的僱員(僱員編號不在經理編號列的僱員)

  SELECT *
  FROM   emp
  WHERE  empno NOT IN(SELECT mgr
                      FROM   emp
                      WHERE  mgr IS NOT NULL);
  或:
  SELECT *
  FROM   emp outer
  WHERE  NOT EXISTS(SELECT 'X'
                    FROM   emp
                    WHERE  mgr=outer.empno);
  或:
  SELECT *
  FROM   emp
  WHERE  empno NOT IN (SELECT NVL(mgr,0)
                       FROM   emp);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章