SQL 使用WITH AS 的好處


使用WITH AS提高性能簡化嵌套SQL

 
 
一. WITH  AS 的含義
     WITH  AS 短語,也叫做子查詢部分(subquery factoring),可以讓你做很多事情,定義一個SQL片斷,該SQL片斷會
被整個SQL語句所用到。有的時候,是為了讓SQL語句的可讀性更高些,也有可能是在 UNION  ALL 的不同部分,作為提供數
據的部分。 
特別對於 UNION  ALL 比較有用。因為 UNION  ALL 的每個部分可能相同,但是如果每個部分都去執行一遍的話,則成本太高,
所以可以使用 WITH  AS 短語,則只要執行一遍即可。如果 WITH  AS 短語所定義的表名被調用兩次以上,則優化器會自動將
WITH  AS 短語所獲取的數據放入一個 TEMP 表里,如果只是被調用一次,則不會。而提示materialize則是強制將 WITH  AS
短語里的數據放入一個全局臨時表里。很多查詢通過這種方法都可以提高速度。
二.使用方法
先看下面一個嵌套的查詢語句:
select  from  person.StateProvince  where  CountryRegionCode  in 
          ( select  CountryRegionCode  from  person.CountryRegion  where  Name  like  'C%' ) 上面的查詢語句使用了一個子查詢。雖然這條SQL語句並不復雜,但如果嵌套的層次過多,會使SQL語句非常難以閱
讀和維護。因此,也可以使用表變量的方式來解決這個問題。
SQL語句如下:
declare  @t  table (CountryRegionCode nvarchar(3)) 
insert  into  @t(CountryRegionCode)  ( select  CountryRegionCode  from  person.CountryRegion  where  Name  like  'C%'
 
select  from  person.StateProvince  where  CountryRegionCode 
                      in  ( select  from  @t) 
 
     雖然上面的SQL語句要比第一種方式更復雜,但卻將子查詢放在了表變量@t中,這樣做將使SQL語句更容易維護,但又
會帶來另一個問題,就是性能的損失。由於表變量實際上使用了臨時表,從而增加了額外的I/O開銷,因此,表變量的方式
並不太適合數據量大且頻繁查詢的情況。為此,在SQL Server 2005中提供了另外一種解決方案,這就是公用表表達式(CTE),使用CTE,可以增加SQL語句的可維護性,同時,CTE要比表變量的效率高得多。
下面是CTE的語法:
WITH  <common_table_expression> [ ,n ] ] 
<common_table_expression>::= 
         expression_name [ ( column_name [ ,n ] ) ] 
     AS 
         ( CTE_query_definition )
 
現在使用CTE來解決上面的問題,SQL語句如下:
with 
cr  as 
     select  CountryRegionCode  from  person.CountryRegion  where  Name  like  'C%' 
 
select  from  person.StateProvince  where  CountryRegionCode  in  ( select  from  cr) 
 
     其中cr是一個公用表表達式,該表達式在使用上與表變量類似,只是SQL Server 2005在處理公用表表達式的方式上有
所不同。
在使用CTE時應注意如下幾點:
1. CTE后面必須直接跟使用CTE的SQL語句(如 select insert update 等),否則,CTE將失效。如下面的SQL語句將無法正
常使用CTE:
with 
cr  as 
     select  CountryRegionCode  from  person.CountryRegion  where  Name  like  'C%' 
select  from  person.CountryRegion   -- 應將這條SQL語句去掉
-- 使用CTE的SQL語句應緊跟在相關的CTE后面-- 
select  from  person.StateProvince  where  CountryRegionCode  in  ( select  from  cr) 
 
 
2. CTE后面也可以跟其他的CTE,但只能使用一個 with ,多個CTE中間用逗號(,)分隔,如下面的SQL語句所示:
with 
cte1  as 
     select  from  table1  where  name  like  'abc%' 
), 
cte2  as 
     select  from  table2  where  id > 20 
), 
cte3  as 
     select  from  table3  where  price < 100 
select  a.*  from  cte1 a, cte2 b, cte3 c  where  a.id = b.id  and  a.id = c.id 
 
 
3. 如果CTE的表達式名稱與某個數據表或視圖重名,則緊跟在該CTE后面的SQL語句使用的仍然是CTE,當然,后面的SQL語句
使用的就是數據表或視圖了,如下面的SQL語句所示:
--  table1是一個實際存在的表
with 
table1  as 
     select  from  persons  where  age < 30 
select  from  table1   --  使用了名為table1的公共表表達式
select  from  table1   --  使用了名為table1的數據表
 
 
4. CTE 可以引用自身,也可以引用在同一 WITH  子句中預先定義的CTE。不允許前向引用。
5. 不能在CTE_query_definition 中使用以下子句:
(1)COMPUTE 或COMPUTE  BY
(2) ORDER  BY (除非指定了 TOP  子句)
(3) INTO
(4)帶有查詢提示的 OPTION  子句
(5) FOR  XML
(6) FOR  BROWSE
 
6. 如果將CTE 用在屬於批處理的一部分的語句中,那么在它之前的語句必須以分號結尾,如下面的SQL所示:
declare  @s nvarchar(3) 
set  @s =  'C%' 
;   -- 必須加分號
with 
t_tree  as 
     select  CountryRegionCode  from  person.CountryRegion  where  Name  like  @s 
select  from  person.StateProvince  where  CountryRegionCode  in  ( select  from  t_tree)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM