亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > SQL Server > 正文

SQL點滴9—使用with語句來寫一個稍微復雜sql語句,附加和子查詢的性能對比

2019-11-03 08:33:10
字體:
來源:轉載
供稿:網友
今天偶爾看到sql中也有with關鍵字,好歹也寫了幾年的sql語句,居然第一次接觸,無知啊??戳艘晃徊┲鞯奈恼?,自己添加了一些內容,做了簡單的總結,這個語句還是第一次見到,學習了。我從簡單到復雜地寫,希望高手們不要見笑。下面的sql語句設計到三個表,表的內容我用txt文件復制進去,這里不妨使用上一個隨筆介紹的建立端到端的package的方法將這些表導入到數據庫中,具體的就不說了。

從這里下載文件employees.txt,customers.txt,orders.txt

參考文章:http://www.cnblogs.com/wwan/archive/2011/02/24/1964279.html

使用package導入數據:http://www.cnblogs.com/tylerdonet/archive/2011/04/17/2017471.html

簡單的聚合

從orders表中選擇各個年份共有共有多少客戶訂購了商品

  •  第一種寫法,我們可以寫成這樣
    1select YEAR(o.orderdate) orderyear,COUNT(distinct(custid)) numCusts
    2from Sales.Orders o
    3group by YEAR(o.orderdate)
    4go
    要注意的是如果把group by YEAR(o.orderdata)換成group by orderyear就會出錯,這里涉及到sql語句的執行順序問題,有時間再了解一下          
  • 第二種寫法,
    1select orderyear,COUNT(distinct(custid))numCusts
    2from (select YEAR(orderdate) as orderyear,custid from sales.orders) as D
    3group by orderyear
    4go
    在from語句中先得到orderyear,然后再select語句中就不會出現沒有這個字段的錯誤了
  • 第三種寫法,
    1select orderyear,COUNT(distinct(custid)) numCusts
    2from (select YEAR(orderdate),custid from sales.orders) as D(orderyear,custid)
    3group by orderyear
    4go
    在as D后面加上選擇出的字段,是不是更加的清楚明了呢!
  • 第四種寫法,with出場了
    1with c as(
    2select YEAR(orderdate) orderyear, custid from sales.orders)
    3select orderyear,COUNT(distinct(custid)) numCusts from c group by orderyear
    4go
    with可以使語句更加的經湊,下面是權威解釋?! ?BR>    
    指定臨時命名的結果集,這些結果集稱為公用表表達式 (CTE)。該表達式源自簡單查詢,并且在單條 SELECT、INSERT、UPDATE、MERGE 或 DELETE 語句的執行范圍內定義。該子句也可用在 CREATE VIEW 語句中,作為該語句的 SELECT 定義語句的一部分。公用表表達式可以包括對自身的引用。這種表達式稱為遞歸公用表達式?!              ?/EM>

                                                ----MSDN

  • 第五種寫法,也可以借鑒第三種寫法,這樣使語句更加清楚明了,便于維護
    1 with c(orderyear,custid) as(
    2  select YEAR(orderdate),custid from sales.orders)
    3  select orderyear,COUNT(distinct(custid)) numCusts from c group by c.orderyear
    4  go
    上面5中寫法都得到相同的結果,如下圖1:圖1

添加計算

  • 現在要求要求計算出訂單表中每年比上一年增加的客戶數目,這個稍微復雜
    1 with yearcount as(
    2  select YEAR(orderdate) orderyear,COUNT(distinct(custid)) numCusts from sales.orders group by YEAR(orderdate))
    3  select cur.orderyear curyear,cur.numCusts curNumCusts,PRv.orderyear prvyear,prv.numCusts prvNumCusts,cur.numCusts-prv.numCusts growth
    4  from yearcount cur left join yearcount prv on cur.orderyear=prv.orderyear+1
    5 go
    這里兩次使用到with結果集。查詢得到的結果如下圖2

    圖2

復雜的計算

  • 查找客戶id,這些客戶和所有來自美國的雇員至少有一筆交易記錄,查詢語句如下
    1 with TheseEmployees as(
    2 select empid from hr.employees where country='USA'),
    3 CharacteristicFunctions as(
    4 select custid,
    5 case when custid in (select custid from sales.orders as o where o.empid=e.empid) then 1 else 0 end as charfun
    6 from sales.customers as c cross join TheseEmployees as e)
    7 select custid,min(charfun) from CharacteristicFunctions group by custid having min(charfun)=1
    8 go
    這里嵌套with語句,第with語句查找美國雇員的id,第二個語句使用這個結果和擁有客戶的客戶id和擁有關系標識做笛卡爾積運算。最后從這個笛卡爾積中通過標識找到最終的custid。
    結果如下圖3

    圖3

這里只有簡單地介紹,沒有深入,高手們不要見笑啊。



---------------------------------------------------------分界線----------------------------------------------------------

with語句和子查詢的性能比較

在博友SingleCat的提醒下,對with語句做一些性能測試,這里使用的測試工具是SQL Server Profile。我選擇了最后一個語句,因為這個語句比較復雜一點。開始的時候單獨執行一次發現他們的差別不大,就差幾個毫秒,后來想讓他們多執行幾次,連續執行10

次看看執行的結果。下面貼出測試用的語句。

1 /*with查詢*/
2 declare @withquery varchar(5000)
3 declare @execcount int=0
4 set @withquery='with TheseEmployees as(
5 select empid from hr.employees where country=N''USA''),
6 CharacteristicFunctions as(
7 select custid,
8 case when custid in (select custid from sales.orders as o where o.empid=e.empid) then 1 else 0 end as charfun
9 from sales.customers as c cross join TheseEmployees as e)
10 select custid from CharacteristicFunctions group by custid having min(charfun)=1 order by custid
11 '
12 while @execcount<10
13 begin
14 exec (@withquery);
15 set @execcount=@execcount+1
16 end
17
18 /*子查詢*/
19 declare @subquery varchar(5000)
20 declare @execcount int=0
21 set @subquery='select custid from Sales.Orders where empid in
22 (select empid from HR.Employees where country = N''USA'') group by custid
23 having count(distinct empid)=(select count(*) from HR.Employees where country = N''USA'');
24 '
25 while @execcount<10
26 begin
27 exec (@subquery);
28 set @execcount=@execcount+1
29 end

SQL Server Profile中截圖如下

從圖中可以看到子查詢語句的執行時間要少于with語句,我覺得主要是with查詢中有一個cross join做了笛卡爾積的關系,于是又實驗了上面的那個簡單一點的,下面是測試語句。

1 /*with語句*/
2 declare @withquery varchar(5000)
3 declare @execcount int=0
4 set @withquery='with c(orderyear,custid) as(
5 select YEAR(orderdate),custid from sales.orders)
6 select orderyear,COUNT(distinct(custid)) numCusts from c group by c.orderyear'
7 while @execcount<100
8 begin
9 exec (@withquery);
10 set @execcount=@execcount+1
11 end
12
13 /*子查詢*/
14 declare @subquery varchar(5000)
15 declare @execcount int=0
16 set @subquery='select orderyear,COUNT(distinct(custid)) numCusts
17 from (select YEAR(orderdate),custid from sales.orders) as D(orderyear,custid)
18 group by orderyear'
19 while @execcount<100
20 begin
21 exec (@subquery);
22 set @execcount=@execcount+1
23 end

 

這次做10次查詢還是沒有多大的差距,with語句用10個duration,子查詢用了11個,有時候還會翻過來。于是把執行次數改成100,這次還是子查詢使用的時間要少,截圖如下

最終結論,子查詢好比with語句效率高。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美色欧美亚洲高清在线视频| 91在线播放国产| 亚洲一区二区久久久| 自拍偷拍亚洲区| 亚洲男人天天操| 久久久久久av| 精品magnet| 亚洲国产精品va在线看黑人动漫| 91精品国产91久久久| 久久精品91久久香蕉加勒比| 深夜福利91大全| 国产精品久久久久久久久久新婚| 亚洲福利在线播放| 亚洲人成电影网站色| 欧美三级欧美成人高清www| 国产成+人+综合+亚洲欧洲| 欧美俄罗斯性视频| 欧美大片在线影院| 国产精品91久久久久久| 欧美日韩精品在线播放| 一区二区亚洲精品国产| 欧美日韩高清在线观看| 福利精品视频在线| 97人人爽人人喊人人模波多| 91高潮精品免费porn| 国产亚洲欧美日韩一区二区| 欧美日韩国产999| 日韩美女主播视频| 国产精品福利网站| 午夜精品一区二区三区在线视频| 日韩美女激情视频| 亚洲第一网站免费视频| 自拍亚洲一区欧美另类| 久久影院中文字幕| 91精品国产91久久久久久| 亚洲人成电影在线| 97国产真实伦对白精彩视频8| 亚洲视频专区在线| 一区二区三区 在线观看视| 精品亚洲一区二区三区在线观看| 亚洲free性xxxx护士hd| 欧美午夜性色大片在线观看| 日韩亚洲成人av在线| 中文字幕日韩欧美在线| 色综合伊人色综合网站| 在线视频免费一区二区| 国产成人小视频在线观看| 91亚洲国产精品| 亚洲欧美激情精品一区二区| 欧美极品美女视频网站在线观看免费| 亚洲国产中文字幕在线观看| 久久中文字幕一区| 日韩欧美国产激情| 中文字幕欧美在线| 日韩精品免费在线视频观看| 欧美中文在线免费| 成人在线小视频| 亚洲精品视频播放| 亚洲欧美一区二区三区情侣bbw| 日韩国产高清污视频在线观看| 日本亚洲欧洲色| 一区二区av在线| 欧美黑人一级爽快片淫片高清| 亚洲第一男人av| 91亚洲国产成人久久精品网站| 日韩专区在线观看| 欧美黄色片视频| 日韩免费精品视频| 日韩欧美aⅴ综合网站发布| 亚洲国产精品高清久久久| 91在线观看免费高清完整版在线观看| 国产精品福利在线观看网址| 在线中文字幕日韩| 26uuu另类亚洲欧美日本老年| 性欧美xxxx交| 久久久女女女女999久久| 国产男女猛烈无遮挡91| 亚洲男人av电影| 久久精品亚洲热| 久久国产精品影视| 国产精品视频在线播放| 国产日韩中文在线| 欧美日产国产成人免费图片| 国产69精品99久久久久久宅男| 国产91精品黑色丝袜高跟鞋| 久久久免费高清电视剧观看| 在线观看成人黄色| 国产美女高潮久久白浆| 日韩在线视频中文字幕| 午夜精品久久久久久久99热| 91久久久久久久久久久久久| 亚洲专区在线视频| 亚洲国产精品悠悠久久琪琪| 91九色精品视频| 欧美肥老太性生活视频| 岛国av一区二区三区| 8x拔播拔播x8国产精品| 亚洲网站视频福利| 久久久久免费视频| 亚洲一区国产精品| 亚洲欧美激情另类校园| 亚洲欧美一区二区三区四区| 国产精品一区二区三区久久久| 中文字幕在线日韩| 日韩美女免费视频| 亚洲国产欧美一区二区丝袜黑人| 国产美女高潮久久白浆| 欧美性视频精品| 欧美成人免费视频| 精品国产一区二区在线| 日韩欧美视频一区二区三区| 欧美日本高清一区| 欧美一区二区.| 91国产精品视频在线| 欧美激情国产高清| 欧美巨猛xxxx猛交黑人97人| 国产精品中文久久久久久久| 国产国产精品人在线视| 亚洲性线免费观看视频成熟| 国产精品久久久久久久久久三级| 91夜夜揉人人捏人人添红杏| 这里只有精品久久| 欧美亚洲另类制服自拍| 欧美激情久久久久久| 亚洲毛片在线看| 国产精自产拍久久久久久蜜| 精品在线欧美视频| 亚洲福利视频二区| 日韩美女主播视频| 中文字幕一区二区精品| 欧美丰满少妇xxxxx做受| 在线电影欧美日韩一区二区私密| 国产欧美精品xxxx另类| 日韩二区三区在线| 欧美成人精品激情在线观看| 久久久999国产精品| 日韩黄在线观看| 久久人人爽人人爽爽久久| 国产精品jvid在线观看蜜臀| 国产一区二区三区欧美| 亚洲电影免费观看高清| 国产精品嫩草影院久久久| 人人做人人澡人人爽欧美| 97超碰国产精品女人人人爽| 91精品国产色综合久久不卡98口| 都市激情亚洲色图| 久久久久五月天| 久久影视电视剧免费网站| 国产精品欧美在线| 色综合天天狠天天透天天伊人| 欧美日韩aaaa| 欧美视频二区36p| 亚洲日本成人女熟在线观看| 日产精品久久久一区二区福利| 久久影视电视剧免费网站清宫辞电视| 亚洲第一福利视频| 麻豆精品精华液| 亚洲国产精品va在线看黑人| 国产第一区电影| 日韩精品在线免费播放| 国产精品久久综合av爱欲tv| 国产精品久久久久久久久久小说| 久久人91精品久久久久久不卡| 亚洲国产精品国自产拍av秋霞|