行轉列:SQL SERVER PIVOT與用法解釋

行轉列:SQL SERVER PIVOT與用法解釋

在數據庫操做中,有些時候咱們遇到須要實現「行轉列」的需求,例如一下的表爲某店鋪的一週收入狀況表: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用法。結果仍是硬的經過例子和別人的博文再加上思考才弄懂了,因此若是各位看了本篇以後仍不能理解,那很正常,配合例子再加上本身思考,慢慢的定能理解。

相關文章
相關標籤/搜索