1. 程式人生 > >用SQL實現結果集的各種轉換----結果集轉成多列

用SQL實現結果集的各種轉換----結果集轉成多列

      之前一篇講述瞭如何將結果集轉成一列,下面介紹如何將一個結果集轉為多列。

      假設原資料表如圖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開始。

       執行下面的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所示的效果了!