SQL點(diǎn)滴之使用with語句來寫一個(gè)稍微復(fù)雜sql語句
今天偶爾看到sql中也有with關(guān)鍵字,好歹也寫了幾年的sql語句,居然***次接觸,無知啊。看了一位博主的文章,自己添加了一些內(nèi)容,做了簡單的總結(jié),這個(gè)語句還是***次見到,學(xué)習(xí)了。我從簡單到復(fù)雜地寫,希望高手們不要見笑。下面的sql語句設(shè)計(jì)到三個(gè)表,表的內(nèi)容我用txt文件復(fù)制進(jìn)去,這里不妨使用上一個(gè)隨筆介紹的建立端到端的package的方法將這些表導(dǎo)入到數(shù)據(jù)庫中,具體的就不說了。
簡單的聚合
從orders表中選擇各個(gè)年份共有共有多少客戶訂購了商品
***種寫法,我們可以寫成這樣
- select YEAR(o.orderdate) orderyear,COUNT(distinct(custid)) numCusts
- from Sales.Orders o
- group by YEAR(o.orderdate)
- go
要注意的是如果把group by YEAR(o.orderdata)換成group by orderyear就會(huì)出錯(cuò),這里涉及到sql語句的執(zhí)行順序問題,有時(shí)間再了解一下
第二種寫法,
- select orderyear,COUNT(distinct(custid))numCusts
- from (select YEAR(orderdate) as orderyear,custid from sales.orders) as D
- group by orderyear
- go
在from語句中先得到orderyear,然后再select語句中就不會(huì)出現(xiàn)沒有這個(gè)字段的錯(cuò)誤了
第三種寫法,
- select orderyear,COUNT(distinct(custid)) numCusts
- from (select YEAR(orderdate),custid from sales.orders) as D(orderyear,custid)
- group by orderyear
- go
在as D后面加上選擇出的字段,是不是更加的清楚明了呢!
第四種寫法,with出場了
- with c as(
- select YEAR(orderdate) orderyear, custid from sales.orders)
- select orderyear,COUNT(distinct(custid)) numCusts from c group by orderyear
- go
with可以使語句更加的經(jīng)湊,下面是權(quán)威解釋。
指定臨時(shí)命名的結(jié)果集,這些結(jié)果集稱為公用表表達(dá)式 (CTE)。該表達(dá)式源自簡單查詢,并且在單條 SELECT、INSERT、UPDATE、MERGE 或 DELETE 語句的執(zhí)行范圍內(nèi)定義。該子句也可用在 CREATE VIEW 語句中,作為該語句的 SELECT 定義語句的一部分。公用表表達(dá)式可以包括對(duì)自身的引用。這種表達(dá)式稱為遞歸公用表達(dá)式?! ?
----MSDN
第五種寫法,也可以借鑒第三種寫法,這樣使語句更加清楚明了,便于維護(hù)
- with c(orderyear,custid) as(
- select YEAR(orderdate),custid from sales.orders)
- select orderyear,COUNT(distinct(custid)) numCusts from c group by c.orderyear
- go
上面5中寫法都得到相同的結(jié)果,如下圖1:
圖1
添加計(jì)算
現(xiàn)在要求要求計(jì)算出訂單表中每年比上一年增加的客戶數(shù)目,這個(gè)稍微復(fù)雜
- with yearcount as(
- select YEAR(orderdate) orderyear,COUNT(distinct(custid)) numCusts from sales.orders group by YEAR(orderdate))
- select cur.orderyear curyear,cur.numCusts curNumCusts,prv.orderyear prvyear,prv.numCusts prvNumCusts,cur.numCusts-prv.numCusts growth
- from yearcount cur left join yearcount prv on cur.orderyear=prv.orderyear+1
- go
這里兩次使用到with結(jié)果集。查詢得到的結(jié)果如下圖2
圖2
復(fù)雜的計(jì)算
查找客戶id,這些客戶和所有來自美國的雇員至少有一筆交易記錄,查詢語句如下
- with TheseEmployees as(
- select empid from hr.employees where country='USA'),
- CharacteristicFunctions as(
- select custid,
- case when custid in (select custid from sales.orders as o where o.empid=e.empid) then 1 else 0 end as charfun
- from sales.customers as c cross join TheseEmployees as e)
- select custid,min(charfun) from CharacteristicFunctions group by custid having min(charfun)=1
- go
這里嵌套with語句,第with語句查找美國雇員的id,第二個(gè)語句使用這個(gè)結(jié)果和擁有客戶的客戶id和擁有關(guān)系標(biāo)識(shí)做笛卡爾積運(yùn)算。***從這個(gè)笛卡爾積中通過標(biāo)識(shí)找到最終的custid。
結(jié)果如下圖3
圖3
這里只有簡單地介紹,沒有深入,高手們不要見笑啊。
【編輯推薦】