sql行列旋轉


一,行轉列

先建立測試數據 

if OBJECT_ID('week_income') is not null
drop table week_income
go
create table week_income
(
    employee varchar(10),
    weekname varchar(10),
    income int
)
go
insert into week_income
select '張三','星期一',1000 union all
select '張三','星期二',2000 union all
select '張三','星期三',1500 union all
select '張三','星期四',2000 union all
select '張三','星期五',3000 union all
select '張三','星期六',4000 union all
select '張三','星期日',5000 union all
select '李四','星期一',1000 union all
select '李四','星期二',2000 union all
select '李四','星期三',1500 union all
select '李四','星期四',2000 union all
select '李四','星期五',3000 union all
select '李四','星期六',4000 union all
select '李四','星期日',8000 

select * from week_income

 

1.1 用傳統的case when 語法實現行轉列。

select employee as '社員'
      ,sum(case weekname when '星期一' then income else 0 end) as '星期一'
      ,sum(case weekname when '星期二' then income else 0 end) as '星期二'
      ,sum(case weekname when '星期三' then income else 0 end) as '星期三'
      ,sum(case weekname when '星期四' then income else 0 end) as '星期四'
      ,sum(case weekname when '星期五' then income else 0 end) as '星期五'
      ,sum(case weekname when '星期六' then income else 0 end) as '星期六'
      ,sum(case weekname when '星期日' then income else 0 end) as '星期日'                              
from week_income
group by employee

1.2 用sqlserver2005以后新增加的pivot語法實現行轉列。 

pivot的語法如下: 

SELECT <non-pivoted column>, 
    [first pivoted column] AS <column name>, 
    [second pivoted column] AS <column name>, 
    ... 
    [last pivoted column] AS <column name> 
FROM 
    (<SELECT query that produces the data>) 
   AS <alias for the source query> 
PIVOT 
( 
    <aggregation function>(<column being aggregated>) 
FOR 
[<column that contains the values that will become column headers>] 
    IN ( [first pivoted column], [second pivoted column], 
    ... [last pivoted column]) 
) AS <alias for the pivot table> 
<optional ORDER BY clause>;
select employee  as '社員',[星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日] --step 3
from (select employee ,weekname,income from week_income) t -- step 2
pivot
(
    --step 1
    sum(income) for weekname in([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日])
) b

pivot分為3個步驟:

1,進行行列轉換

sum(income) for weekname in([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日])
注意:聚合函數sum等是決定重復行數據的處理方法,比如有兩個星期一,就把這兩個值合並了。

2,定義檢索數據源(select employee ,weekname,income from week_income) t

注意別名t不能省略。這里要特別注意employee這一列並沒有在步驟1中出現,sqlserver會默認按employee進行分組,這個功能挺棒的。

3,選擇結果集中的列,全部選擇可以用*。

employee  as '社員',[星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日]
注意:可以對列名取別名,也可以只檢索其中的部分列,而不必全部檢索出所有列。

轉換結果

二,列轉行

以上面的轉換結果作為數據表,我們先把結果導入到一張tmp的表中

select * into tmp from (
select employee  as '社員',[星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日]
from (select employee ,weekname,income from week_income) t
pivot
(
    sum(income) for weekname in([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日])
) b
) c

select * from tmp 

然后,我們將星期一到星期日這幾列轉換到行上。

2.1 用傳統的union all方法。

select 社員 as employee,'星期一' as weekname, 星期一 as income from tmp union all
select 社員 as employee,'星期二' as weekname, 星期二 as income from tmp union all
select 社員 as employee,'星期三' as weekname, 星期三 as income from tmp union all
select 社員 as employee,'星期四' as weekname, 星期四 as income from tmp union all
select 社員 as employee,'星期五' as weekname, 星期五 as income from tmp union all
select 社員 as employee,'星期六' as weekname, 星期六 as income from tmp union all
select 社員 as employee,'星期日' as weekname, 星期日 as income from tmp
order by 社員

2.2 用sqlserver2005以后新增的unpivot方法。

select 社員 as employee, weekname,income
from (select 社員,[星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日] from tmp) a
unpivot
(
    income for weekname in ([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日] )
) b

unpivot是pivot的逆操作,income和weekname都是需要創建的新列,income指代數據的值,weekname指代列名的值。

轉換后的結果和我們最初建立的表一模一樣

 三,動態實現行列旋轉

上面的方式,都是代碼寫了幾個固定值旋轉,沒有實現動態列,擴展性不強。

要實現動態,主要使用拼sql的方式實現,以行轉列的傳統寫法做個例子,其他的可以舉一反三。

declare @sql as varchar(4000)
set @sql = 'select employee as ''社員'''

select @sql = @sql + ',sum(case weekname when ''' + weekname + ''' then income else 0 end) as ''' + weekname + ''''
from (
    select distinct weekname from week_income) a
set  @sql =@sql + ' from week_income    '
set  @sql =@sql + ' group by employee    '
print @sql
exec (@sql)

結果也是這樣


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM