您的位置:首页 > 其它

03. 行列转换写法小结

2014-06-23 17:17 225 查看
原文:03. 行列转换写法小结行列转换,通常有2种方法,一是CASE WHEN/UNION;一是PIVOT/UNPIVOT。对于行值或列数不固定的情况,需要用动态SQL。

[b]一. 行转列[/b]

--drop table RowToCol
create table RowToCol
(
ID int,
Code varchar(10),
Value int
)
Go
insert RowToCol
select 1,'Item1',1000 union all
select 1,'Item2',1000 union all
select 1,'Item3',500 union all
select 2,'Item1',2000 union all
select 2,'Item2',0 union all
select 3,'Item1',1000 union all
select 3,'Item3',500
GO
select * 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 Item3
from 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 Item3
from 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 a
set @sql = @sql + ' from RowToCol group by ID'
--print @sql
exec(@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 Code
set @sql = '[' + @sql + ']'
--print @sql
exec ('select * from (select * from RowToCol) a pivot (max(value) for Code in (' + @sql + ')) b')


[b]二. 列转行[/b]

--drop table ColToRow
create table ColToRow
(
ID int,
Item1 int,
Item2 int,
Item3 int
)
GO
insert into ColToRow
select '1',1000,1000,500 union all
select '2',2000,0,0 union all
select '3',1000,0,500
GO
select * 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 ColToRow
union all
select ID,Code='Item2',Value=Item2 from ColToRow
union all
select ID,Code='Item3',Value=Item3 from ColToRow
order 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 ColToRow'
from syscolumns
where name <> N'ID' and ID = object_id('ColToRow')
order by colid asc
--print @sql
exec(@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 <> N'ID' and ID = object_id('ColToRow')
set @sql = '[' + @sql + ']'
--print @sql
exec('select ID , Code , Value from ColToRow unpivot (Value for Code in(' + @sql + ')) t')
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: