亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

SQL點(diǎn)滴10—使用with語(yǔ)句來(lái)寫一個(gè)稍微復(fù)雜sql語(yǔ)

系統(tǒng) 2163 0
原文: SQL點(diǎn)滴10—使用with語(yǔ)句來(lái)寫一個(gè)稍微復(fù)雜sql語(yǔ)句,附加和子查詢的性能對(duì)比

?今天偶爾看到sql中也有with關(guān)鍵字,好歹也寫了幾年的sql語(yǔ)句,居然第一次接觸,無(wú)知啊。看了一位博主的文章,自己添加了一些內(nèi)容,做了簡(jiǎn)單的總結(jié),這個(gè)語(yǔ)句還是第一次見(jiàn)到,學(xué)習(xí)了。我從簡(jiǎn)單到復(fù)雜地寫,希望高手們不要見(jiàn)笑。下面的sql語(yǔ)句設(shè)計(jì)到三個(gè)表,表的內(nèi)容我用txt文件復(fù)制進(jìn)去,這里不妨使用上一個(gè)隨筆介紹的建立端到端的package的方法將這些表導(dǎo)入到數(shù)據(jù)庫(kù)中,具體的就不說(shuō)了。

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

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

使用package導(dǎo)入數(shù)據(jù): http://www.cnblogs.com/tylerdonet/archive/2011/04/17/2017471.html

簡(jiǎn)單的聚合

從orders表中選擇各個(gè)年份共有共有多少客戶訂購(gòu)了商品

  • ?第一種寫法,我們可以寫成這樣
              
    1 select YEAR (o.orderdate) orderyear, COUNT ( distinct (custid)) numCusts
    2 from Sales.Orders o
    3 group by YEAR (o.orderdate)
    4 go
    要注意的是如果把group by YEAR(o.orderdata)換成group by orderyear就會(huì)出錯(cuò),這里涉及到sql語(yǔ)句的執(zhí)行順序問(wèn)題,有時(shí)間再了解一下          
  • 第二種寫法,
              
    1 select orderyear, COUNT ( distinct (custid))numCusts
    2 from ( select YEAR (orderdate) as orderyear,custid from sales.orders) as D
    3 group by orderyear
    4 go
    在from語(yǔ)句中先得到orderyear,然后再select語(yǔ)句中就不會(huì)出現(xiàn)沒(méi)有這個(gè)字段的錯(cuò)誤了
  • 第三種寫法,
              
    1 select orderyear, COUNT ( distinct (custid)) numCusts
    2 from ( select YEAR (orderdate),custid from sales.orders) as D(orderyear,custid)
    3 group by orderyear
    4 go
    在as D后面加上選擇出的字段,是不是更加的清楚明了呢!
  • 第四種寫法,with出場(chǎng)了
              
    1 with c as (
    2 select YEAR (orderdate) orderyear, custid from sales.orders)
    3 select orderyear, COUNT ( distinct (custid)) numCusts from c group by orderyear
    4 go
    with可以使語(yǔ)句更加的經(jīng)湊,下面是權(quán)威解釋。  

    指定臨時(shí)命名的結(jié)果集,這些結(jié)果集稱為公用表表達(dá)式 (CTE)。該表達(dá)式源自簡(jiǎn)單查詢,并且在單條 SELECT、INSERT、UPDATE、MERGE 或 DELETE 語(yǔ)句的執(zhí)行范圍內(nèi)定義。該子句也可用在 CREATE VIEW 語(yǔ)句中,作為該語(yǔ)句的 SELECT 定義語(yǔ)句的一部分。公用表表達(dá)式可以包括對(duì)自身的引用。這種表達(dá)式稱為遞歸公用表達(dá)式。               

----MSDN

  • 第五種寫法,也可以借鑒第三種寫法,這樣使語(yǔ)句更加清楚明了,便于維護(hù)
              
    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中寫法都得到相同的結(jié)果,如下圖1: 圖1

添加計(jì)算

  • 現(xiàn)在要求要求計(jì)算出訂單表中每年比上一年增加的客戶數(shù)目,這個(gè)稍微復(fù)雜
              
    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結(jié)果集。查詢得到的結(jié)果如下圖2

    圖2

復(fù)雜的計(jì)算

  • 查找客戶id,這些客戶和所有來(lái)自美國(guó)的雇員至少有一筆交易記錄,查詢語(yǔ)句如下
              
    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語(yǔ)句,第with語(yǔ)句查找美國(guó)雇員的id,第二個(gè)語(yǔ)句使用這個(gè)結(jié)果和擁有客戶的客戶id和擁有關(guān)系標(biāo)識(shí)做笛卡爾積運(yùn)算。最后從這個(gè)笛卡爾積中通過(guò)標(biāo)識(shí)找到最終的custid。
    結(jié)果如下圖3
    SQL點(diǎn)滴10—使用with語(yǔ)句來(lái)寫一個(gè)稍微復(fù)雜sql語(yǔ)句,附加和子查詢的性能對(duì)比
    圖3

這里只有簡(jiǎn)單地介紹,沒(méi)有深入,高手們不要見(jiàn)笑啊。

?

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

with語(yǔ)句和子查詢的性能比較

在博友 SingleCat 的提醒下,對(duì) with 語(yǔ)句做一些性能測(cè)試,這里使用的測(cè)試工具是 SQL Server Profile 。我選擇了最后一個(gè)語(yǔ)句,因?yàn)檫@個(gè)語(yǔ)句比較復(fù)雜一點(diǎn)。開(kāi)始的時(shí)候單獨(dú)執(zhí)行一次發(fā)現(xiàn)他們的差別不大,就差幾個(gè)毫秒,后來(lái)想讓他們多執(zhí)行幾次,連續(xù)執(zhí)行 10

次看看執(zhí)行的結(jié)果。下面貼出測(cè)試用的語(yǔ)句。

        
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 中截圖如下

從圖中可以看到子查詢語(yǔ)句的執(zhí)行時(shí)間要少于with語(yǔ)句,我覺(jué)得主要是with查詢中有一個(gè)cross join做了笛卡爾積的關(guān)系,于是又實(shí)驗(yàn)了上面的那個(gè)簡(jiǎn)單一點(diǎn)的,下面是測(cè)試語(yǔ)句。

      
1 /* with語(yǔ)句 */
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次查詢還是沒(méi)有多大的差距,with語(yǔ)句用10個(gè)duration,子查詢用了11個(gè),有時(shí)候還會(huì)翻過(guò)來(lái)。于是把執(zhí)行次數(shù)改成100,這次還是子查詢使用的時(shí)間要少,截圖如下

SQL點(diǎn)滴10—使用with語(yǔ)句來(lái)寫一個(gè)稍微復(fù)雜sql語(yǔ)句,附加和子查詢的性能對(duì)比

最終結(jié)論,子查詢好比with語(yǔ)句效率高。

SQL點(diǎn)滴10—使用with語(yǔ)句來(lái)寫一個(gè)稍微復(fù)雜sql語(yǔ)句,附加和子查詢的性能對(duì)比


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 国产精品久久精品福利网站 | 欧美日比视频 | 国产成人精品日本亚洲专一区 | 色青青草原桃花久久综合 | 亚洲精品第一国产麻豆 | ass曰本人乱妇ass | 欧美精品在线一区二区三区 | 夜夜躁狠狠躁日日躁视频 | 99国产精品热久久久久久 | 国产精品一区二区手机看片 | 四房婷婷在线视频播放 | 亚洲国产成人精彩精品 | 亚洲欧美日韩图片 | 国产色婷婷视频在线观看 | 天天干天天舔天天操 | 成人精品国产亚洲 | 噜噜色综合| 亚洲国产日韩欧美 | 91精品免费不卡在线观看 | 日日干夜夜欢 | 97在线视频免费播放 | 不卡视频在线 | 青青青青久久精品国产一百度 | 四虎在线最新永久免费播放 | 国产一级毛片视频 | 人人综合| 在线a毛片免费视频观看 | 人人澡人人干 | 色老头成人免费视频天天综合 | 中文字幕一区二区三区精品 | 99在线观看免费 | 欧美一欧美一级毛片 | 天色噜噜噜噜 | 日韩精品视频一区二区三区 | 久久精品夜色国产 | 亚洲图片综合网 | 99热国产这里只有精品99 | 国产成人精品cao在线 | 一区二区三区www | 国产伦精品一区二区三区女 | 欧美成人精品欧美一级乱黄 |