with..as oracle的用法

with..as oracle的用法

--語法:

with tempName as (select ....)
select ...

--例:現在要從1-19中得到11-14。一般的sql如下:
select * from
(
            --模擬生一個20行的數據
             SELECT LEVEL AS lv
               FROM DUAL
         CONNECT BY LEVEL < 20
) tt
WHERE tt.lv > 10 AND tt.lv < 15

--使用With as 的SQL爲:
with TT as(
                --模擬生一個20行的數據
                 SELECT LEVEL AS lv
                 FROM DUAL
                CONNECT BY LEVEL < 20
             ) 
select lv from TT
WHERE lv > 10 AND lv < 15

/*With查詢語句不是以select開始的,而是以“WITH”關鍵字開頭
可認爲在真正進行查詢之前預先構造了一個臨時表TT,之後便可多次使用它做進一步的分析和處理

WITH Clause方法的優點
增加了SQL的易讀性,如果構造了多個子查詢,結構會更清晰;更重要的是:“一次分析,多次使用”,
這也是爲什麼會提供性能的地方,達到了“少讀”的目標。
第一種使用子查詢的方法表被掃描了兩次,而使用WITH Clause方法,表僅被掃描一次。
這樣可以大大的提高數據分析和查詢的效率。
另外,觀察WITH Clause方法執行計劃,其中“SYS_TEMP_XXXX”便是在運行過程中構造的中間統計結果臨時表。*/
-----*************************在視圖中使用WITH語句進行連接
CREATE OR REPLACE VIEW WITH_V AS
WITH DEPT_V AS (SELECT * FROM DEPT),
EMP_V AS (SELECT * FROM EMP)
SELECT D.DNAME,D.LOC,E.* FROM EMP_V E
LEFT JOIN DEPT_V D
ON D.DEPTNO = E.DEPTNO
-----*************************WITH語句的使用例子:
/*查詢出部門的總薪水大於所有部門平均總薪水的部門。部門表s_dept,員工表s_emp。
分析:做這個查詢,首先必須計算出所有部門的總薪水,然後計算出總薪水的平均薪水,
再篩選出部門的總薪水大於所有部門總薪水平均薪水的部門。那麼第1 步with 查詢查出所有部門的總薪水,
第2 步用with 從第1 步獲得的結果表中查詢出平均薪水,最後利用這兩次 的with 查詢比較總薪水大於平均薪水的結果,如下:
*/
WITH DEPT_COSTS AS --查詢出部門的總工資
 (SELECT D.DNAME, SUM(E.SAL) DEPT_TOTAL
 FROM DEPT D, EMP E
 WHERE E.DEPTNO = D.DEPTNO
 GROUP BY D.DNAME),
 AVE_COST AS --查詢出部門的平均工資,在後一個WITH語句中可以引用前一個定義的WITH語句
 (SELECT SUM(DEPT_TOTAL) / COUNT(*) AVG_SUM FROM DEPT_COSTS)
 SELECT
-----*************************
 /*一、WITH AS的含義
        WITH AS短語,也叫做子查詢部分(subquery factoring),可以定義一個SQL片斷,該SQL片斷會被整個SQL語句所用到。
		特別對於UNION ALL比較有用。因爲UNION ALL的每個部分可能相同,但是如果每個部分都去執行一遍的話,則成本太高,
		所以可以使用WITH AS短語,則只要執行一遍即可。如果WITH AS短語所定義的表名被調用兩次以上,則優化器會自動將WITH AS
		短語所獲取的數據放入一個TEMP表裏,如果只是被調用一次,則不會。而提示materialize則是強制將WITH AS短語裏的數據放入
		一個全局臨時表裏。很多查詢通過這種方法都可以提高速度。

二、WITH AS的使用實例
從A表中查詢某個字段出來,如果沒有從B表中查詢,如果A,B表中都沒有,則輸出ERROR
*/
with sql1 as 
     (select to_char(id) myid from a),
sql2 as 
     (select to_char(id) myid from b where not exists 
     (select * from sql1 where rownum > 5))
select * from sql1
union all
select * from sql2
union all
select 'error' from dual
       where not exists (select * from sql1 where rownum > 5) and not exists 
       (select * from sql2 where rownum > 2);


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