之前一篇講述瞭如何將結果集轉成一列,下面介紹如何將一個結果集轉爲多列。
假設原數據表如圖1所示,現在要將如圖2顯示的結果集轉換爲如圖3所示的結果集。
圖1 圖2 圖3
由圖1得到圖2的SQL語句爲
select ProvinceName,CityName from CityTable
也許讀者可能想到用上一篇文章說的思路來解決將如圖2所示的結果集轉換爲如圖3所示的結果集,我們這裏不妨試下,執行以下SQL代碼
select
case when ProvinceName='福建' then CityName else '' end as '福建',
case when ProvinceName='湖南' then CityName else '' end as '湖南',
case when ProvinceName='浙江' then CityName else '' end as '浙江'
from CityTable
結果顯示爲如圖4所示
圖4
然後我們再將每個Case返回的結果進行求最大數即求聚集函數MAX(),SQL如下:
select
MAX(case when ProvinceName='福建' then CityName else '' end) as '福建',
MAX(case when ProvinceName='湖南' then CityName else '' end) as '湖南',
MAX(case when ProvinceName='浙江' then CityName else '' end) as '浙江'
from CityTable
執行結果如圖5所示
圖5
顯然由圖4得到圖5是因爲一個MAX()得出每一列的最大值,字符型數據也有最大值,顯然最後結果集顯示的只有一行數據,而這明顯不是我們要的結果。
要得到我們想要得到如圖3所示的結果,有一種方式是通過SQL的窗口函數來實現,先複製SQL代碼給大家看看
接下來講解下上面這段SQL語句。
1~6用了公用表表達式CTE(優點:1、沒有像臨時表那樣耗性能,也沒有像子查詢那樣可讀性差。2、增強了可維護性和效率)定義了一個臨時數據集(暫且這麼描述),然後在第12行中引用這個公用表數據集,關於CTE大家可以到其他網站再好好了解,這裏不再詳細說明。同時上面的SQL也涉及到了SQL的窗口函數row_number() over(partition by ProvinceName order By CityName).
row_number() over (order by ColumnName)函數是SQL2005在SQL2000的基礎上新增的一個函數,作用是根據ColumnName這個列進行排序並編號,編號從1開始。
舉個例子:
select *,
row_number() over( order by CityName)
as RN from CityTable
執行上面的SQL語句,將結果集按照CityName這個列進行排序,並且編號,編號從1開始,將得到如圖6所示的結果集
圖6
而partition by ProvinceName是將整個結果集先根據ProvinceName進行分區(這裏是把每個省劃分爲一個分區),再對各個不同的分區根據CityName進行排序,並重新編號,編號從1開始。
關於窗口函數具體請看下一篇文章http://blog.csdn.net/bin_520_yan/archive/2010/10/31/5977571.aspx
執行下面的SQL語句
select *,
row_number() over(partition by ProvinceName order by CityName)
as RN from CityTable
執行結果如圖7所示
圖7
然後將這個結果集進行類似上一篇文章所述的方式,利用case when else end語句將行轉換爲列,執行下面SQL語句
with NewTable as
(
select *,
row_number() over(partition by ProvinceName order by CityName)
as RN from CityTable
)
select
case when ProvinceName='福建' then CityName else '' end as '福建',
case when ProvinceName='湖南' then CityName else '' end as '湖南',
case when ProvinceName='浙江' then CityName else '' end as '浙江',
RN
from NewTable
執行結果如圖8所示
圖8
看了上面的結果,大家可能有個想法,可以將RN爲相同值的行放在一起,對RN、ProvinceName及CityName進行分組,如下
with NewTable as
(
select *,
row_number() over(partition by ProvinceName order by CityName)
as RN from CityTable
)
select
case when ProvinceName='福建' then CityName else '' end as '福建',
case when ProvinceName='湖南' then CityName else '' end as '湖南',
case when ProvinceName='浙江' then CityName else '' end as '浙江',
RN
from NewTable
group by RN,ProvinceName,CityName
執行上面的SQL語句將得到如圖9所示結果
圖9
可能大家已經明白了接下來該怎麼做了,是的,接下來我們求每組的MAX()聚集函數的值、並且只按RN進行分組即可,如下SQL語句
with NewTable as
(
select *,
row_number() over(partition by ProvinceName order by CityName)
as RN from CityTable
)
select
MAX(case when ProvinceName='福建' then CityName else '' end) as '福建',
MAX(case when ProvinceName='湖南' then CityName else '' end) as '湖南',
MAX(case when ProvinceName='浙江' then CityName else '' end) as '浙江',
RN
from NewTable
group by RN
執行上面的SQL語句就得到我們想要的如圖3所示的效果了!