在數據庫操做中,有些時候咱們遇到須要實現「行轉列」的需求,例如一下的表爲某店鋪的一週收入狀況表:html
WEEK_INCOME(WEEK VARCHAR(10),INCOME DECIMAL)
咱們先插入一些模擬數據:sql
INSERT INTO WEEK_INCOME SELECT '星期一',1000 UNION ALL SELECT '星期二',2000 UNION ALL SELECT '星期三',3000 UNION ALL SELECT '星期四',4000 UNION ALL SELECT '星期五',5000 UNION ALL SELECT '星期六',6000 UNION ALL SELECT '星期日',7000
通常咱們最常用的查詢是查詢一週中天天或某幾天的收入,例如查詢週一至週日所有的收入:數據庫
SELECT WEEK,INCOME FROM WEEK_INCOME
獲得以下的查詢結果集:函數
WEEK INCOME
星期一 1000
星期二 2000
星期三 3000
星期四 4000
星期五 5000
星期六 6000
星期日 7000post
可是在一些狀況下(每每是某些報表中),咱們但願在一行中顯示週一至週日的收入,這時候查詢結果集應該是這樣的:google
星期一 星期二 星期三 星期四 星期五 星期六 星期日
1000 2000 3000 4000 5000 6000 7000spa
這種狀況下,SQL查詢語句能夠這樣寫:設計
SELECT SUM(CASE WEEK WHEN '星期一' THEN INCOME END) AS [星期一], SUM(CASE WEEK WHEN '星期二' THEN INCOME END) AS [星期二], SUM(CASE WEEK WHEN '星期三' THEN INCOME END) AS [星期三], SUM(CASE WEEK WHEN '星期四' THEN INCOME END) AS [星期四], SUM(CASE WEEK WHEN '星期五' THEN INCOME END) AS [星期五], SUM(CASE WEEK WHEN '星期六' THEN INCOME END) AS [星期六], SUM(CASE WEEK WHEN '星期日' THEN INCOME END) AS [星期日] FROM WEEK_INCOME
可是,在SQL SERVER 2005中提供了更爲簡便的方法,這就是"PIVOT"關係運算符。(相反的「列轉行」是UNPIVOT),如下是使用PIVOT實現「行轉列」的SQL語句htm
SELECT [星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日] FROM WEEK_INCOME PIVOT ( SUM(INCOME) for [week] in([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日]) )TBL
請參考MSDN中關於PIVOT的用法:blog
http://technet.microsoft.com/zh-cn/library/ms177410(v=sql.105).aspx
可是MSDN上的描述太過於規範嚴肅,我看了半天還沒弄清楚怎樣使用PIVOT,搞不清楚PIVOT裏面的語法的含義。因而又google了不少資料,以及經過上面提到的WEEK_INCOME表例子做了試驗,最終搞清楚了其用法。在網上有篇博文解釋的很好:T-SQL PIVOT語法剖析與實戰,基本上我要寫的就是參照該博文,再加上本身一點我的理解。
要理解PIVOT語法,就是要清楚微軟爲何這樣設計PIVOT,但我相信是現實需求催生設計思路,因此歸根到底咱們仍是要弄清楚什麼是「行轉列」:
正常狀況下的查詢結果是這樣:
星期一 1000
星期二 2000
星期三 3000
星期四 4000
星期五 5000
星期六 6000
星期日 7000
行轉列後是這樣:
星期一 星期二 星期三 星期四 星期五 星期六 星期日
1000 2000 3000 4000 5000 6000 7000
也就是說,行轉列後,原來的某個列的值變作了列名,在這裏就是原來WEEK列的值「星期一」,"星期二"..."星期日"邊作了列名,而咱們須要作的另外一個工做就是計算這些列的值(這裏的「計算」其實就是PIVOT裏面的聚合函數(sum,avg等))
如今結合註釋來分析一下PIVOT語法(在這以前最好看看我上面提到博文:T-SQL PIVOT語法剖析與實戰,裏面說到的PIVOT語法的三個步驟挺重要):
SELECT [星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日]--這裏是PIVOT第三步(選擇行轉列後的結果集的列)這裏能夠用「*」表示選擇全部列,也能夠只選擇某些列(也就是某些天) FROM WEEK_INCOME --這裏是PIVOT第二步驟(準備原始的查詢結果,由於PIVOT是對一個原始的查詢結果集進行轉換操做, 因此先查詢一個結果集出來)這裏能夠是一個select子查詢,但爲子查詢時候要指定別名,不然語法錯誤 PIVOT ( SUM(INCOME) for [week] in([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日]) --這裏是PIVOT第一步驟,也是核心的地方,進行行轉列操做。聚合函數SUM表示你須要怎樣處理轉換後的列的值, 是總和(sum),仍是平均(avg)仍是min,max等等。例如若是week_income表中有兩條數據而且其week都是「星期一」, 其中一條的income是1000,另外一條income是500,那麼在這裏使用sum,行轉列後「星期一」這個列的值固然是1500了。 後面的for [week] in([星期一],[星期二]...)中 for [week]就是說將week列的值分別轉換成一個個列,也就是「以值變列」。 可是須要轉換成列的值有可能有不少,咱們只想取其中幾個值轉換成列,那麼怎樣取呢?就是在in裏面了,好比我此刻只想看工 做日的收入,在in裏面就只寫「星期一」至「星期五」(注意,in裏面是原來week列的值,"以值變列")。總的來講, SUM(INCOME) for [week] in([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日])這句的意思若是直譯出來, 就是說:將列[week]值爲"星期一","星期二","星期三","星期四","星期五","星期六","星期日"分別轉換成列, 這些列的值取income的總和。 )TBL--別名必定要寫
以上是我對PIVOT的理解,我盡所能表達出來。不過話說回來,我的的理解的方式也不一樣,就如我開始看了不少篇博文,都沒有搞清楚PIVOT用法。結果仍是硬的經過例子和別人的博文再加上思考才弄懂了,因此若是各位看了本篇以後仍不能理解,那很正常,配合例子再加上本身思考,慢慢的定能理解。