Pivot 通俗的说法是将列值转换成列名,即行转列。
语法是
table_source PIVOT ( 聚合函数(value_column) FOR pivot_column IN(<column_list>) )
原理是:对 Pivot_column 之外的Columns进行分组,统计Pivot_column的聚合值。
1,创建示例数据
create table dbo.usr ( name varchar(10), age int, sex char(1) ) go insert into dbo.usr values(‘a‘,18,‘f‘),(‘b‘,19,‘m‘),(‘c‘,20,‘f‘),(‘d‘,21,‘m‘) go
2,对age之外的数据列name,sex进行分组,然后求age的聚合值。
select p.* from dbo.usr u PIVOT ( count(u.age) for u.age in([18],[19],[20],[21]) ) as p
结果显示,分组列是name和sex,而聚合列是age,age的值作为列名了。
表dbo.usr 的alias 能够用于pivot语句中,实际上,如果一个表被pivot之后,这个表和之后的pivot语句重新组合成一个新的虚拟表,alias是p,而u对pivot之外的语句不再有效。
dbo.usr u PIVOT ( count(u.age) for u.age in([18],[19],[20],[21]) ) as p
3,知道pivot的原理之后,可以很轻易地写出pivot的等价写法,使用group by 分组求聚合值 ,并使用 case when 语句将列值作为列名返回。
select u.name,u.sex, sum(case when u.age=18 then 1 else 0 end) as [18], sum(case when u.age=19 then 1 else 0 end) as [19], sum(case when u.age=20 then 1 else 0 end) as [20], sum(case when u.age=21 then 1 else 0 end) as [21] from dbo.usr u group by u.name,u.sex
4,操作pviot的结果集
select p.sex,count(0) as user_count, sum(p.[18]) as [age=18], sum(p.[19]) as [age=19], sum(p.[20]) as [age=20], sum(p.[21]) as [age=21] from dbo.usr u PIVOT ( count(age) for age in([18],[19],[20],[21]) ) as p group by p.sex
5,动态Pivot写法,需要使用动态sql,拼接列值
静态pivot写法的弊端是:如果表中的age值发生变化,静态pivot就不能对增加的age值进行聚合并显示出来。
declare @sql nvarchar(max) declare @columnlist nvarchar(max) set @columnlist=N‘‘ ;with cte as ( select distinct age from dbo.usr ) select @columnlist+=‘sum(case when u.age=‘+cast(age as varchar(10))+N‘ then 1 else 0 end) as [‘+cast(age as varchar(10))+N‘],‘ from cte select @columnlist=SUBSTRING(@columnlist,1,len(@columnlist)-1) select @sql= N‘select u.name,u.sex,‘ +@columnlist +N‘from dbo.usr u group by u.name,u.sex‘ exec(@sql)
或
declare @sql nvarchar(max) declare @columnlist nvarchar(max) declare @agelist nvarchar(max) set @columnlist=N‘‘ set @agelist=N‘‘ ;with cte as ( select distinct age from dbo.usr ) select @columnlist+=N‘sum(p.[‘+cast(age as varchar(11))+N‘]) as [age=‘+cast(age as varchar(11))+N‘], ‘, @agelist+=N‘[‘+cast(age as varchar(11))+N‘],‘ from cte select @columnlist=SUBSTRING(@columnlist,1,len(@columnlist)-1),@agelist=SUBSTRING(@agelist,1,len(@agelist)-1) select @sql=N‘select p.sex,count(0) as user_count, ‘ +@columnlist +N‘from dbo.usr u PIVOT ( count(age) for age in(‘+@agelist+N‘) ) as p group by p.sex‘ exec (@sql)
原文:http://www.cnblogs.com/ljhdo/p/4995554.html