1. 程式人生 > >關於with as 作為查詢片段的使用和與臨時表#Table的比較

關於with as 作為查詢片段的使用和與臨時表#Table的比較

一.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)

    CTE除了可以簡化巢狀SQL語句外,還可以進行遞迴呼叫,關於這一部分的內容將在下一篇文章中介紹。

關於oracle with table as 建立臨時表的用法示例

1、with table as 相當於建個臨時表(用於一個語句中某些中間結果放在臨時表空間的SQL語句),Oracle 9i 新增WITH語法,可以將查詢中的子查詢命名,放到SELECT語句的最前面。

語法就是
with tempname as (select ....)
select ...

例子:
with t as (select * from emp where depno=10)
select * from t where empno=xxx

with
wd as (select did,arg(salary) 平均工資 from work group by did),
em as (select emp.*,w.salary from emp left join work w on emp.eid = w.eid)
select * from wd,em where wd.did =em.did and wd.平均工資>em.salary;



2、何時被清除
臨時表不都是會話結束就自動被PGA清除嘛! 但with as臨時表是查詢完成後就被清除了!
23:48:58 [email protected]> with aa as(select * from dept)
23:57:58 2 select * from aa;

DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

已用時間: 00: 00: 00.12
23:58:06 [email protected]> select * from aa;
select * from aa
*
第 1 行出現錯誤:
ORA-00942: 表或檢視不存在


已用時間: 00: 00: 00.02
23:58:14 [email protected]>

3、就這一功能來說,子查詢就可以達到啊,為什麼要用with呢? 用with有什麼好處?
都能寫,但執行計劃不同的。當有多個相似子查詢的時候,用with寫公共部分,因為子查詢結果在記憶體臨時表中,執行效率當然就高啦~

4、問題:
有張表資料如下:
aaa 高
bbb 低
aaa 低
aaa 高
bbb 低
bbb 高
需要得到下列結果,
高 低
aaa 2 1
bbb 1 2
問 SQL 語句怎麼寫??

答案:
with tt as (
select 'aaa' id, '高' value from dual union all
select 'bbb' id, '低' value from dual union all
select 'aaa' id, '低' value from dual union all
select 'aaa' id, '高' value from dual union all
select 'bbb' id, '低' value from dual union all
select 'bbb' id, '高' value from dual)
SELECT id,
COUNT(decode(VALUE, '高', 1)) 高,
COUNT(decode(VALUE, '低', 1)) 低
FROM tt
GROUP BY id;
===================================================================
擴充套件:
Oracle9i新增WITH語法,可以將查詢中的子查詢命名,放到SELECT語句的最前面。

  一個簡單的例子:

SQL> WITH
2 SEG AS (SELECT SEGMENT_NAME, SUM(BYTES)/1024 K FROM USER_SEGMENTS GROUP BY SEGMENT_NAME),
3 OBJ AS (SELECT OBJECT_NAME, OBJECT_TYPE FROM USER_OBJECTS)
4 SELECT O.OBJECT_NAME, OBJECT_TYPE, NVL(S.K, 0) SIZE_K
5 FROM OBJ O, SEG S
6 WHERE O.OBJECT_NAME = S.SEGMENT_NAME (+)
7 ;
OBJECT_NAME OBJECT_TYPE SIZE_K
------------------------------ ------------------- ----------
DAIJC_TEST TABLE 128
P_TEST PROCEDURE 0
IND_DAIJC_TEST_C1 INDEX 128

  通過WITH語句定義了兩個子查詢SEG和OBJ,在隨後的SELECT語句中可以直接對預定義的子查詢進行查詢。從上面的例子也可以看出,使用WITH語句,將一個包含聚集、外連線等操作SQL清晰的展現出來。

  WITH定義的子查詢不僅可以使查詢語句更加簡單、清晰,而且WITH定義的子查詢還具有在SELECT語句的任意層均可見的特點。

  即使是在WITH的定義層中,後定義的子查詢都可以使用前面已經定義好的子查詢:

SQL> WITH
2 Q1 AS (SELECT 3 + 5 S FROM DUAL),
3 Q2 AS (SELECT 3 * 5 M FROM DUAL),
4 Q3 AS (SELECT S, M, S + M, S * M FROM Q1, Q2)
5 SELECT * FROM Q3;
S M S+M S*M
---------- ---------- ---------- ----------
8 15 23 120

  利用WITH定義查詢中出現多次的子查詢還能帶來效能提示。Oracle會對WITH進行效能優化,當需要多次訪問WITH定義的子查詢時,Oracle會將子查詢的結果放到一個臨時表中,避免同樣的子查詢多次執行,從而有效的減少了查詢的IO數量。

WITH能用在SELECT語句中,UPDATE和DELETE語句也是支援WITH語法的,只是需要版本支援:
http://www.oracle.com.cn/viewthread.php?tid=83530

=============================================================================
with
sql1 as (select to_char(a) s_name from test_tempa),
sql2 as (select to_char(b) s_name from test_tempb where not exists (select s_name from sql1 where rownum=1))
select * from sql1
union all
select * from sql2
union all
select 'no records' from dual
where not exists (select s_name from sql1 where rownum=1)
and not exists (select s_name from sql2 where rownum=1);

再舉個簡單的例子

with a as (select * from test)

select * from a;

其實就是把一大堆重複用到的SQL語句放在with as 裡面,取一個別名,後面的查詢就可以用它

這樣對於大批量的SQL語句起到一個優化的作用,而且清楚明瞭


起因上文,時間統計資料。由於統計的資料需要重複訪問一個小的結果集。

原先的解決方案

使用臨時表

SELECT ObservationDatetime,RainfallPerMinute, Temperature, BatteryVoltage
 INTO #temp FROM View_rainfall WHERE [email protected] and DATEDIFF(day,ObservationDatetime,@ObservationDate) = 0

後來看了SQL Server2005技術內幕發現

WITH AS可以代替上面的解決方案

效能大大提升

相關推薦

關於with as 作為查詢片段的使用臨時#Table比較

一.WITH AS的含義     WITH AS短語,也叫做子查詢部分(subquery factoring),可以讓你做很多事情,定義一個SQL片斷,該SQL片斷會被整個SQL語句所用到。有的時候,是為了讓SQL語句的可讀性更高些,也有可能是在UNION ALL的不同

Oracle學習筆記:with as查詢用法

  With as短語,也叫做子查詢部分(subquery factoring),可以定義一個SQL片斷,該SQL片斷會被整個SQL語句用到。該語句會在真正的查詢之前預先構造一個臨時表,之後可以多次使用做進一步的分析和處理。   優勢:   1.可以使SQL語句的可讀性更高;  2.一次分析,多次使用,提

資料庫學習(四)with as (補充 nvl count 函式)

  with as 的專業解釋我這就不詳細說明了,我這就梳理下我自己的實踐應用,就是根據某個條件查詢出結果集放在一個臨時表裡面,可以建立多個臨時表,然後再從這些臨時表中查詢出要的資料。   參考資料:https://www.cnblogs.com/Niko12230/p/5945133.html 

[轉]變量臨時比較

sel ren 還需 fin 關於 del opera 統計信息 sele 本文轉自;http://www.cnblogs.com/CareySon/archive/2012/06/11/TableVariableAndTempTable.html 關於表

SQL基本操作——select into臨時

weight sql基本操作 bsp 臨時表 arc table rst get 需要 SELECT INTO 語句從一個表中選取數據,然後把數據插入另一個表中,常用於創建表的備份復件或者用於對記錄進行存檔。 --制作 "Persons" 表的備份復件: SELECT *

動態執行Sql語句臨時的問題(物件名無效)

exec('selectIDENTITY(int,1,1)  as ID,fnum,into  #yuecu  from  store_store where  '+@Parameter)  select  XX,XX1,XX2  from  #yuecu 這樣建立一個臨時表

SQL資料庫 儲存過程、索引、檢視臨時

--資料庫程式設計2. --儲存過程  exec  --執行速度快:儲存過程是編譯之後的語句,儲存在資料庫的內容;儲存過程的操作只有一次。--系統儲存過程 存放在master資料庫中,都以“sp_”或“xp_”開頭 exec sp_databasesexec sp_r

MySQL中Update、select聯用操作單、多,及檢視臨時的區別

一、MySQL中使用從表A中取出資料來更新表B的內容 例如:要update表data中的一些列屬性,但是修改屬性的內容來源是來自表chanpin。SQL語言中不要顯示的出現select關鍵字 update data d,chanpin c set d.zhulei=c.z

sql語句使用內嵌檢視臨時示例

某些時候,查詢需要將資料與其他一些可能只能通過執行 GROUP BY 然後執行標準查詢才能收集的資料進行聯接。例如,如果要查詢最新五個定單的有關資訊,您首先需要知道是哪些定單。這可以使用返回定單 ID 的 SQL 查詢來檢索。此資料就會儲存在臨時表(這是一個常用技術)中,然後

ORACLE創建臨時事務global temporary table 查詢臨時with tempName as (select ) select

query 問題 weight select 別名 onf bold hellip course 創建臨時事務表只是保存當前會話(session)用到的數據,數據只在事務或會話期間存在,可規避多線程調用數據沖突問題 -- Create table create glo

SSM-MyBatis-05:Mybatis中別名,sql片段模糊查詢加getMapper

接口 過程 ase exce bat -c 多次 nts log ------------吾亦無他,唯手熟爾,謙卑若愚,好學若饑------------- 簡單概述一下本講 別名,sql片段簡單寫一下,模糊查詢多寫一點 一。別名    <typeAliases&

SQL 語句遞歸查詢 With AS 查找所有子節點

商務部 ins AR where reat parent ren nvarchar tab create table #EnterPrise( Department nvarchar(50),--部門名稱 ParentDept nvarchar(50),-

ORACLE WITH AS 用法,創建臨時

進一步 有用 cin AI 運行 結構 nbsp index ring 語法: with tempName as (select ....)select ... –針對一個別名with tmp as (select * from tb_name) –針對多個別名wi

T-SQL查詢WITH AS 遞歸計算某部門的所有上級機構或下級機構

area t-sql union sel lec where 需要 _id with as drop table #Area; CREATE TABLE #Area ( id INT NOT NULL, city_name NVARCHAR(100)

6.4 Replace Temp with Query 以查詢取代臨時變數

將表示式提煉到一個獨立方法中,將這個臨時變數的所有引用點替換為對新方法的呼叫 更多精彩 更多技術部落格,請移步 asing1elife’s blog 前置條件 該方法通常是 6.1 Extract Method 提煉方法 的前置條件

Oracle之with asupdate用法

許久不用,又忘了,做個記錄 update test b set b.code=(with t as(select t.id,code||'_'||row_number() over(partition by code order by id) codefrom test t)select a.code fr

大話資料結構讀書筆記艾提拉總結 查詢演算法 排序演算法比較好 第1章資料結構緒論 1 第2章演算法 17 第3章線性 41 第4章棧佇列 87 第5章串 123 第6章樹 149 第7章圖 21

大話資料結構讀書筆記艾提拉總結   查詢演算法 和排序演算法比較好     第1章資料結構緒論 1 第2章演算法 17 第3章線性表 41 第4章棧與佇列 87 第5章串 123 第6章樹 149 第7章圖 211

sql優化:with as 作 union all的子查詢 來避免多次掃描

語法: 1.結構: with 別名 as ( 公共sql片段 ) 2.CTE(公共表示式)後面必須直接緊跟使用CTE的SQL語句,否則失效; 如: 1) with cr as (select CountryRegionCode from person.CountryR

關於Oracle中的aswith as 的用法

在Oracle中as關鍵字不能用於指定表的別名,在Oracle中指定表的別名時只需在原有表名和表的別名之間用空格分隔即可, 但可以用於指定列的別名,但在儲存過程中如果列的別名與原有列名相同,在執行時會報錯(編譯時不會出錯),其他情況下 列的別名可以與列名本身相同。 在查詢oracle中as關鍵字的用

用Kibanalogstash快速搭建實時日誌查詢、收集分析系統

  Logstash是一個完全開源的工具,他可以對你的日誌進行收集、分析,並將其儲存供以後使用(如,搜尋),您可以使用它。說到搜尋,logstash帶有一個web介面,搜尋和展示所有日誌。 kibana 也是一個開源和免費的工具,他可以幫助您彙總、分析和搜尋重要資料日誌並提供友好的web介面。他可以為 L