麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 數(shù)據(jù)庫 > SQL Server > 正文

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

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

從這里下載文件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è)年份共有共有多少客戶訂購了商品

  •  第一種寫法,我們可以寫成這樣
    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就會(huì)出錯(cuò),這里涉及到sql語句的執(zhí)行順序問題,有時(shí)間再了解一下          
  • 第二種寫法,
    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語句中就不會(huì)出現(xiàn)沒有這個(gè)字段的錯(cuò)誤了
  • 第三種寫法,
    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出場(chǎng)了
    1with c as(
    2select YEAR(orderdate) orderyear, custid from sales.orders)
    3select orderyear,COUNT(distinct(custid)) numCusts from c group by orderyear
    4go
    with可以使語句更加的經(jīng)湊,下面是權(quán)威解釋。  
        
    指定臨時(shí)命名的結(jié)果集,這些結(jié)果集稱為公用表表達(dá)式 (CTE)。該表達(dá)式源自簡(jiǎn)單查詢,并且在單條 SELECT、INSERT、UPDATE、MERGE 或 DELETE 語句的執(zhí)行范圍內(nèi)定義。該子句也可用在 CREATE VIEW 語句中,作為該語句的 SELECT 定義語句的一部分。公用表表達(dá)式可以包括對(duì)自身的引用。這種表達(dá)式稱為遞歸公用表達(dá)式。               

                                                ----MSDN

  • 第五種寫法,也可以借鑒第三種寫法,這樣使語句更加清楚明了,便于維護(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,這些客戶和所有來自美國的雇員至少有一筆交易記錄,查詢語句如下
    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,第二個(gè)語句使用這個(gè)結(jié)果和擁有客戶的客戶id和擁有關(guān)系標(biāo)識(shí)做笛卡爾積運(yùn)算。最后從這個(gè)笛卡爾積中通過標(biāo)識(shí)找到最終的custid。
    結(jié)果如下圖3

    圖3

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



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

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

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

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

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

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

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個(gè)duration,子查詢用了11個(gè),有時(shí)候還會(huì)翻過來。于是把執(zhí)行次數(shù)改成100,這次還是子查詢使用的時(shí)間要少,截圖如下

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


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 手机在线看片国产 | 久久综合艹| 3344永久免费| 国产亚洲精品久久午夜玫瑰园 | 一级毛片在线观看免费 | 国产精选电影免费在线观看网站 | av在线免费观看播放 | 亚洲小视频在线观看,com | 国产无遮挡一级毛片 | 九九热精彩视频 | 亚洲骚妻 | 污片视频网站 | 96视频在线免费观看 | 欧美日韩精品一区二区三区不卡 | 亚洲精品久久久久久下一站 | 久久777国产线看观看精品 | 成人在线97| 亚洲成人欧美 | 久久精品探花 | 久久99精品久久 | 日本精品二区 | 天天碰天天操 | 国产一区二区三区在线观看视频 | 欧美性生交xxxxx久久久缅北 | 久久精品国产清自在天天线 | 国产手机av在线 | 新久草视频 | 久久密 | 黄色免费影片 | 国产亚洲激情 | 久久久经典视频 | 亚洲成人久久精品 | 91www成人久久 | 国产一区二区精彩视频 | 91国内精品久久久久免费影院 | 中国洗澡偷拍在线播放 | 黑人日比 | 久草在线高清视频 | 国产精品亚洲精品久久 | 亚洲码无人客一区二区三区 | 看国产毛片 |