行轉列,列轉行是我們在開發過程中經常碰到的問題。行轉列一般通過case when 語句來實作,也可以通過 sql server 2005 新增的運算符pivot來實作。用傳統的方法,比較好了解。層次清晰,而且比較習慣。 但是pivot 、unpivot提供的文法比一系列複雜的select...case 語句中所指定的文法更簡單、更具可讀性。下面我們通過幾個簡單的例子來介紹一下列轉行、行轉列問題。
我們首先先通過一個老生常談的例子,學生成績表(下面簡化了些)來形象了解下行轉列
如果我想知道每位學生的每科成績,而且每個學生的全部成績排成一行,這樣友善我檢視、統計,導出資料
接下來我們來看看第二個小列子。有一個遊戲玩家充值表(僅僅為了說明,舉的一個小例子),
下面來了一個統計資料的需求,要求按日期、支付方式來統計充值金額資訊。這也是一個典型的行轉列的例子。我們可以通過下面的腳本來達到目的
如圖所示,我們這樣隻是得到了這樣的輸出結果,還需進一步處理,才能得到想要的結果
其實行轉列,關鍵是要理清邏輯,而且對分組
(group
by)概念比較清晰。上面兩個列子基本上就是行轉列的類型了。但是有個問題來了,上面是我為了說明弄的一個簡單列子。實際中,可能支付方式特别多,而且邏
輯也複雜很多,可能涉及匯率、手續費等等(曾經做個這樣一個),如果支付方式特别多,我們的case when
會弄出一大堆,确實比較惱火,而且新增一種支付方式,我們還得修改腳本如果把上面的腳本用動态sql改寫一下,我們就能輕松解決這個問題
下面是通過pivot來進行行轉列的用法,大家可以對比一下,确實要簡單、更具可讀性(呵呵,習慣的前提下)
有時可能會出現這樣的錯誤:
消息 325,級别 15,狀态 1,第 9 行
'pivot' 附近有文法錯誤。您可能需要将目前資料庫的相容級别設定為更高的值,以啟用此功能。有關存儲過程 sp_dbcmptlevel 的資訊,請參見幫助。
這個是因為:對更新到 sql
server 2005 或更高版本的資料庫使用 pivot 和 unpivot 時,必須将資料庫的相容級别設定為 90
或更高。有關如何設定資料庫相容級别的資訊,請參閱 sp_dbcmptlevel (transact-sql)。 例如,隻需在執行上面腳本前加上
exec sp_dbcmptlevel test, 90; 就ok了, test 是所在資料庫的名稱。
下面我們來看看列轉行,主要是通過union all ,max來實作。假如有下面這麼一個表
我們可以通過下面的腳本來實作,查詢結果如下圖所示
用unpivot 實作如下: