首页 > 代码库 > 03. 行列转换写法小结

03. 行列转换写法小结

原文:03. 行列转换写法小结

行列转换,通常有2种方法,一是CASE WHEN/UNION;一是PIVOT/UNPIVOT。对于行值或列数不固定的情况,需要用动态SQL。


一. 行转列

--drop table RowToColcreate table RowToCol(ID int,Code varchar(10),Value int)Goinsert RowToCol select 1,Item1,1000 union allselect 1,Item2,1000 union allselect 1,Item3,500 union allselect 2,Item1,2000 union allselect 2,Item2,0 union allselect 3,Item1,1000 union allselect 3,Item3,500 GOselect * from RowToCol

 要得到这样的结果:

IDItem1Item2Item3
110001000500
2200000
310000500


1. CASE WHEN
在SQL Server 2000时,常用的写法,沿用至今。
(1) 静态

select ID,sum(case Code when Item1 then Value else 0 end) as Item1,sum(case Code when Item2 then Value else 0 end) as Item2,sum(case Code when Item3 then Value else 0 end) as Item3from RowToCol group by ID--或者用max也行select ID,max(case Code when Item1 then Value else 0 end) as Item1,max(case Code when Item2 then Value else 0 end) as Item2,max(case Code when Item3 then Value else 0 end) as Item3from RowToCol group by ID

 (2) 动态

在不确定有多少行需要转为列时,先distinct出待转列的值,再拼出包含若干个CASE的SQL语句,然后运行。

declare @sql varchar(8000)set @sql = select ID select @sql = @sql +  , max(case Code when ‘‘‘ + Code + ‘‘‘ then Value else 0 end) [ + Code + ]from (select distinct Code from RowToCol) as aset @sql = @sql +  from RowToCol group by ID--print @sqlexec(@sql)

 

2. PIVOT
PIVOT是SQL Server 2005的新语法,Oracle在11g中也推出了这个语法。
(1) 静态

select * from (select * from RowToCol) a pivot (max(value) for Code in ([Item1],[Item2],[Item3])) b

 (2) 动态

用PIVOT拼写动态SQL时就简单了,只要把后面的列清单整理出来就可以了。

declare @sql varchar(8000)select @sql = isnull(@sql + ],[ , ‘‘) + Code from RowToCol group by Codeset @sql = [ + @sql + ]--print @sqlexec (select * from (select * from RowToCol) a pivot (max(value) for Code in ( + @sql + )) b)

 

二. 列转行

--drop table ColToRowcreate table ColToRow(ID int,Item1 int,Item2 int,Item3 int)GOinsert into ColToRowselect 1,1000,1000,500 union allselect 2,2000,0,0 union allselect 3,1000,0,500 GOselect * from ColToRow

 要得到这样的结果:

IDCodeValue
1Item11000
1Item21000
1Item3500
2Item12000
2Item20
2Item30
3Item11000
3Item20
3Item3500

1. UNION
在SQL Server 2000时,常用的写法,沿用至今。
(1) 静态

select ID,Code=Item1,Value=Item1 from ColToRowunion allselect ID,Code=Item2,Value=Item2 from ColToRowunion allselect ID,Code=Item3,Value=Item3 from ColToRoworder by ID

 SQL Server对于多个UNION的排序,只要在最后加ORDER BY就可以了。

(2) 动态
在不确定有多少列需要转为行时,先借助系统表syscolumns找出待转行的列,再拼出包含若干个UNION语句,然后运行。

declare @sql varchar(8000)select @sql = isnull(@sql +  union all  , ‘‘ ) +  select ID , [Code] =  + quotename(Name , ‘‘‘‘) +  , [Value] =  + quotename(Name) +  from ColToRowfrom syscolumns where name <> NID and ID = object_id(ColToRow)order by colid asc--print @sqlexec(@sql +  order by ID )

 

2. UNPIVOT
UNPIVOT是SQL Server 2005的新语法,Oracle在11g中也推出了这个语法。
(1) 静态

select ID , Code , Value from ColToRow unpivot (Value for Code in([Item1] , [Item2] , [Item3])) t

 (2) 动态

declare @sql varchar(8000)select @sql = isnull(@sql + ],[ , ‘‘) + name from syscolumns where name <> NID and ID = object_id(ColToRow)set @sql = [ + @sql + ]--print @sqlexec(select ID , Code , Value from ColToRow unpivot (Value for Code in( + @sql + )) t)