ORACLE中的子查詢

“子查詢”就是查詢中嵌套着另一個查詢,也即通過SELECT語句的嵌套使用形成子查詢。當我們不知道特定的查詢條件時,可以用子查詢來爲父查詢提供查詢條件以獲得查詢結果。
ORACLE中常見的子查詢有下面幾類:
A、單行子查詢(Single-row subqueries)。
B、多行子查詢(Multirow subqueries)。
C、內部視圖型子查詢(Inline views)。
D、多列子查詢(Multiple-column subqueries)。
在我們繼續詳細討論子查詢之前,先看看寫子查詢的一些特別要注意的地方:
A、子查詢必須放在括號內。
B、子查詢也必須放在比較操作符號的右邊。
C、子查詢最多可以嵌套到255級。
子查詢中不能使用ORDER BY子句,即ORDER BY必須位於查詢的最外層。
一、單行子查詢(Single-Row Subqueries)
單行子查詢並不是最後輸出的結果只能返回一行,而是指子查詢只能返回一行。
有一條規則我們必須記住:
當我們用“等於”比較操作符把子查詢和父查詢嵌套在一起時,父查詢期望從子查詢那裏只得到一行返回值。
例一:
   SELECT ename,deptno,sal FROM EMP
   WHERE deptno=(SELECT deptno FROM dept
WHERE loc=’New York’);
在這個例子中,如果子查詢“SELECT deptno FROM dept WHERE loc=’New York’”只返回一行,則這個例子能正確運行,否則將出錯。原因見前面規則。
其它一些表明是單行子查詢的比較操作符有“>,>=,<,<=,<>”。
 
二、多行子查詢(Multirow Subqueries)
多行子查詢,意味着子查詢返回的結果子集可以是多行。因此,我們通常用集合比較操作符(如:IN, NOT IN)把父查詢和子查詢連接起來。  
例二:
    SELECT ename,job,sal FROM EMP
    WHERE deptno in ( SELECT deptno FROM dept
WHERE dname LIKE ‘A%’);

三、多列子查詢(Multiple-Column Subqueries):
前面兩個例子中,主查詢的WHERE子句中都只有一列。然而,有時需要主查詢處理多列。例如,爲了得到每個部門工資最高的員工信息,可以使用下面的例子。 
例三:
    SELECT deptno,ename,job,sal FROM EMP
    WHERE (deptno,sal) IN (SELECT deptno,MAX(sal) FROM EMP
                         GROUP BY deptno);
    (有關本節演示請參見實驗演示)
     在使用多列子查詢時必須注意:
A、 主查詢中,必須把WHERE子句中需要的多個列用括號括起來,否則發生錯誤。
B、 主查詢WHERE子句中的列與子查詢中返回的列必須匹配。

四、內聯視圖子查詢(inline view Subqueries):
通常的查詢中,FROM子句後面都是具體的表名。然而,我們也可以在FROM後面跟上一個子查詢作爲中間
數據結果集,這個中間結果集就是內聯視圖(inline view)。帶有內聯視圖的子查詢就是內聯視圖子查
詢。
例四:
    SELECT ename,job,sal,rownum
 FROM (SELECT ename,job,sal FROM EMP ORDER BY sal);
從這個例子我們應該注意到:
FROM子句後面的內聯視圖是可以使用ORDER BY子句進行排序的。然而,其它視圖或子查詢是不能用ORDER
BY進行排序的。
另外,我們在內聯視圖可以排序的基礎上,可以使用“TOP-N”查詢得到一些有意義的結果集。例如,可
以用下面的例子在EMP表中找出工資最低的五個員工的信息。
例五:
    SELECT ename,job,sal,rownum
FROM ( SELECT ename,job,sal FROM EMP ORDER BY sal)
        WHERE rownum<=5;
           Rownum是表內部的一個指示行號的列。
五、到此,我們已經瞭解了四類子查詢,但在使用子查詢時還要注意以下幾點:   
A、 在HAVING子句中也可以使用子查詢。
例:
SELECT deptno,job,AVG(sal) FROM EMP
GROUP BY deptno,job
HAVING AVG(sal)>(SELECT sal FROM EMP WHERE ename=’MARTIN’);
(有關本節演示請參見實驗演示)
B、 在一些比較複雜的子查詢中,可能需要多次處理同一個子查詢,爲了優化這一步驟,ORACLE9i引入了“WITH”子句來提高這類子查詢的性能。
例:
    SELECT dname,SUM(sal) AS dept_total
    FROM EMP,DEPT
    WHERE EMP.deptno=DEPT.deptno
    GROUP BY dname
    HAVING SUM(sal)>(SELECT SUM(sal)*1/3
                      FROM EMP,DEPT
                      WHERE EMP.deptno=DEPT.deptno)
    ORDER BY SUM(sal) DESC;
顯然,子查詢“SELECT SUM(sal) FROM EMP,DEPT WHERE EMP.deptno=DEPT.deptno”處理了兩次。因此,可以利用O9i中的下來語法來改善性能:
    WITH summary AS
    ( SELECT dname,SUM(sal) AS dept_total
FROM EMP,DEPT
      WHERE EMP.deptno=DEPT.deptno
      GROUP BY dname )
    SELECT dname,dept_total FROM summary
    WHERE dept_total>(SELECT SUM(dept_total)*1/3 FROM summary)
    ORDER BY dept_total DESC;  
C、在一些子查詢操作,諸如數據分組,可能會產生空值。然而,在子查詢把這些數據集返回給主查詢時又會忽略空值。因此,應特別小心這種情況。


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/cowbane/archive/2009/10/15/4675468.aspx

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