分组+行转列问题,DBA不在,压力很大
- SQL code
-----建表数据 CREATE TABLE [dbo].[stockinfo]( [stockcode] [int] NULL, [yybid] [int] NULL, [yybname] [nvarchar](50) NULL) ON [PRIMARY] insert into [master].[dbo].[stockinfo] values(1,1234,'hello') insert into [master].[dbo].[stockinfo] values(1,1235,'world') insert into [master].[dbo].[stockinfo] values(2,10000,'good') insert into [master].[dbo].[stockinfo] values(2,10001,'better') insert into [master].[dbo].[stockinfo] values(2,10002,'best') insert into [master].[dbo].[stockinfo] values(3,9527,'ios') insert into [master].[dbo].[stockinfo] values(3,9528,'android') insert into [master].[dbo].[stockinfo] values(3,9529,'firefoxos') insert into [master].[dbo].[stockinfo] values(3,9530,'meego') insert into [master].[dbo].[stockinfo] values(3,9531,'BlackBerry') insert into [master].[dbo].[stockinfo] values(4,3389,'port')
stockcode yybid yybname
1 1234hello
1 1235world
2 10000good
2 10001better
2 10002best
3 9527ios
3 9528android
3 9529firefoxos
3 9530meego
3 9531 BlackBerry
43389port
--这个是原表
--现在以stockcode分组
--需求为这样
stockcode yybid_1 yybid_2 yybid_3 yybid_4 yybid_5 yybname_1 yybname_2 yybname_3 yybname_4 yybname_5
1 1234 1235 null null null hello world null null null
2 10000 10001 10002 null null good better best null null
3 9527 9528 9529 9530 9531 ios android firefoxos meego BlackBerry
4 3389 null null null null port null null null null
本来也想用游标插入临时表来做,但是耗时确实很严重。
懂得大大,还望指点一二,先谢谢了!
[解决办法]
- SQL code
--行列互转--摘自中国风博客,引用请标明内容来源--1、行换列if object_id('Class') is not null drop table ClassGoCreate table Class([Student] nvarchar(2),[Course] nvarchar(2),[Score] int)Insert Classselect N'张三',N'语文',78 union allselect N'张三',N'数学',87 union allselect N'张三',N'英语',82 union allselect N'张三',N'物理',90 union allselect N'李四',N'语文',65 union allselect N'李四',N'数学',77 union allselect N'李四',N'英语',65 union allselect N'李四',N'物理',85 Go--2000方法:--动态:declare @s nvarchar(4000)set @s=''Select @s=@s+','+quotename([Course])+'=max(case when [Course]=' +quotename([Course],'''')+' then [Score] else 0 end)'from Class group by[Course]--select @sexec('select [Student]'+@s+' from Class group by [Student]')--生成静态:select [Student], [数学]=max(case when [Course]='数学' then [Score] else 0 end), [物理]=max(case when [Course]='物理' then [Score] else 0 end), [英语]=max(case when [Course]='英语' then [Score] else 0 end), [语文]=max(case when [Course]='语文' then [Score] else 0 end) from Class group by [Student]GO--动态:declare @s nvarchar(4000)Select @s=isnull(@s+',','')+quotename([Course]) from Class group by[Course]select @sexec('select * from Class pivot (max([Score]) for [Course] in('+@s+'))b')--生成静态:select * from Class pivot (max([Score]) for [Course] in([数学],[物理],[英语],[语文]))b--生成格式:/*Student 数学 物理 英语 语文------- ----------- ----------- ----------- -----------李四 77 85 65 65张三 87 90 82 78(2 行受影响)*/go--加上总成绩(学科平均分)--2000方法:--动态:declare @s nvarchar(4000)set @s=''Select @s=@s+','+quotename([Course])+'=max(case when [Course]='+quotename([Course],'''')+'then [Score] else 0 end)'from Class group by[Course]exec('select [Student]'+@s+',[总成绩]=sum([Score]) from Class group by [Student]')--加多一列(学科平均分用avg([Score]))生成动态:select [Student], [数学]=max(case when [Course]='数学' then [Score] else 0 end), [物理]=max(case when [Course]='物理' then [Score] else 0 end), [英语]=max(case when [Course]='英语' then [Score] else 0 end), [语文]=max(case when [Course]='语文' then [Score] else 0 end), [总成绩]=([Score]) --加多一列(学科平均分用avg([Score]))from Class group by [Student]go--2005方法:动态:declare @s nvarchar(4000)Select @s=isnull(@s+',','')+quotename([Course]) from Class group by[Course] --isnull(@s+',','') 去掉字符串@s中第一个逗号exec('select [Student],'+@s+',[总成绩] from (select *,[总成绩]=sum([Score])over(partition by [Student]) from Class) a pivot (max([Score]) for [Course] in('+@s+'))b ')--生成静态:select [Student],[数学],[物理],[英语],[语文],[总成绩] from (select *,[总成绩]=sum([Score])over(partition by [Student]) from Class) a --平均分时用avg([Score])pivot (max([Score]) for [Course] in([数学],[物理],[英语],[语文]))b 生成格式:/*Student 数学 物理 英语 语文 总成绩------- ----------- ----------- ----------- ----------- -----------李四 77 85 65 65 292张三 87 90 82 78 337(2 行受影响)*/go--2、列转行 if not object_id('Class') is null drop table ClassGoCreate table Class([Student] nvarchar(2),[数学] int,[物理] int,[英语] int,[语文] int)Insert Classselect N'李四',77,85,65,65 union allselect N'张三',87,90,82,78Go--2000:动态:declare @s nvarchar(4000)select @s=isnull(@s+' union all ','')+'select [Student],[Course]='+quotename(Name,'''')--isnull(@s+' union all ','') 去掉字符串@s中第一个union all+',[Score]='+quotename(Name)+' from Class'from syscolumns where ID=object_id('Class') and Name not in('Student')--排除不转换的列order by Colidexec('select * from ('+@s+')t order by [Student],[Course]')--增加一个排序生成静态:select * from (select [Student],[Course]='数学',[Score]=[数学] from Class union all select [Student],[Course]='物理',[Score]=[物理] from Class union all select [Student],[Course]='英语',[Score]=[英语] from Class union all select [Student],[Course]='语文',[Score]=[语文] from Class)t order by [Student],[Course]go--2005:动态:declare @s nvarchar(4000)select @s=isnull(@s+',','')+quotename(Name)from syscolumns where ID=object_id('Class') and Name not in('Student') order by Colidexec('select Student,[Course],[Score] from Class unpivot ([Score] for [Course] in('+@s+'))b')goselect Student,[Course],[Score] from Class unpivot ([Score] for [Course] in([数学],[物理],[英语],[语文]))b生成格式:/*Student Course Score------- ------- -----------李四 数学 77李四 物理 85李四 英语 65李四 语文 65张三 数学 87张三 物理 90张三 英语 82张三 语文 78*/这类问题太多了,不想写,自己照着画画就出来了
[解决办法]
- SQL code
declare @sql varchar(max)declare @i int,@max intset @i=1select top 1 @max=count(yybid) from stockinfo group by stockcode order by count(yybid) descwhile @i<=@maxbegin set @sql=isnull(@sql+',','')+' sum(case when rn='+ltrim(@i)+' then yybid else null end) yybid_'+ltrim(@i) set @i=@i+1endset @i=1while @i<=@maxbegin set @sql=isnull(@sql+',','')+' max(case when rn='+ltrim(@i)+' then yybname else null end) yybname'+ltrim(@i) set @i=@i+1endset @sql='select stockcode,'+@sql+' from (select row_number() over(partition by stockcode order by stockcode) rn,* from stockinfo)t group by stockcode'--print @sqlexec(@sql)--查询结果/*stockcode yybid_1 yybid_2 yybid_3 yybid_4 yybid_5 yybname1 yybname2 yybname3 yybname4 yybname5----------- ----------- ----------- ----------- ----------- ----------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------------------------------------------1 1234 1235 NULL NULL NULL hello world NULL NULL NULL2 10000 10001 10002 NULL NULL good better best NULL NULL3 9527 9528 9529 9530 9531 ios android firefoxos meego BlackBerry4 3389 NULL NULL NULL NULL port NULL */