程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> SQL點滴之使用with語句來寫一個稍微復雜sql語句

SQL點滴之使用with語句來寫一個稍微復雜sql語句

編輯:關於SqlServer
 

今天偶爾看到sql中也有with關鍵字,好歹也寫了幾年的sql語句,居然第一次接觸,無知啊。看了一位博主的文章,自己添加了一些內容,做了簡單的總結,這個語句還是第一次見到,學習了。我從簡單到復雜地寫,希望高手們不要見笑。下面的sql語句設計到三個表,表的內容我用txt文件復制進去,這裡不妨使用上一個隨筆介紹的建立端到端的package的方法將這些表導入到數據庫中,具體的就不說了。

簡單的聚合

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

第一種寫法,我們可以寫成這樣

  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就會出錯,這裡涉及到sql語句的執行順序問題,有時間再了解一下

第二種寫法,

  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語句中先得到orderyear,然後再select語句中就不會出現沒有這個字段的錯誤了

第三種寫法,

  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出場了

  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可以使語句更加的經湊,下面是權威解釋。

指定臨時命名的結果集,這些結果集稱為公用表表達式 (CTE)。該表達式源自簡單查詢,並且在單條 SELECT、INSERT、UPDATE、MERGE 或 DELETE 語句的執行范圍內定義。該子句也可用在 CREATE VIEW 語句中,作為該語句的 SELECT 定義語句的一部分。公用表表達式可以包括對自身的引用。這種表達式稱為遞歸公用表達式。 
----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.
  3. orders group by YEAR(orderdate))
  4. select cur.orderyear curyear,cur.numCusts curNumCusts,prv.orderyear prvyear,
  5. prv.numCusts prvNumCusts,
  6. cur.numCusts-prv.numCusts growth
  7. from yearcount cur left join yearcount prv on cur.orderyear=prv.orderyear+1
  8. 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)
  6. then 1 else 0 end as charfun
  7. from sales.customers as c cross join TheseEmployees as e)
  8. select custid,min(charfun) from CharacteristicFunctions group by custid having min(charfun)=1
  9. go

這裡嵌套with語句,第with語句查找美國雇員的id,第二個語句使用這個結果和擁有客戶的客戶id和擁有關系標識做笛卡爾積運算。最後從這個笛卡爾積中通過標識找到最終的custid。

結果如下圖3

圖3

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

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved