当前位置: 代码迷 >> Sql Server >> 求教一个简单的sql 多列转多行 的有关问题
  详细解决方案

求教一个简单的sql 多列转多行 的有关问题

热度:12   发布时间:2016-04-27 12:27:06.0
求教一个简单的sql 多列转多行 的问题
原数据为:2行3列的表
S1 S2 S3
1 2 3
4 5 6

想转换成这样:
S 用户1 用户2
S1 1 4
S2 2 5
S3 3 6

很简单吧,大家帮帮忙~

------解决方案--------------------
楼主:你这个是列转行吧,请看下面的例子:

http://www.douban.com/note/146892684/
------解决方案--------------------
SQL code
贴了算了/*将表数据旋转90度(2007-11-19于海南三亚)将下表数据:A                    b           c           d           e           -------------------- ----------- ----------- ----------- ----------- x                    1           2           3           4y                    5           6           7           8z                    9           10          11          12转化成如下结果:a                    x          y          z          -------------------- ---------- ---------- ---------- b                    1          5          9c                    2          6          10d                    3          7          11e                    4          8          12*/--生成测试数据create table test1(A varchar(20),b int,c int,d int,e int)insert into test1 select 'x',1,2 ,3 ,4insert into test1 select 'y',5,6 ,7 ,8insert into test1 select 'z',9,10,11,12go--生成中间数据表declare @s varchar(8000)set @s = 'create table test2(a varchar(20)'select @s = @s + ',' + A + ' varchar(10)' from test1set @s = @s + ')'exec(@s)print @s--借助中间表实现行列转换declare @name varchar(20)declare t_cursor cursor for select name from syscolumns where id=object_id('test1') and colid > 1 order by colidopen t_cursorfetch next from t_cursor into @namewhile @@fetch_status = 0begin    exec('select ' + @name + ' as t into test3 from test1')    set @s='insert into test2 select ''' + @name + ''''    select @s = @s + ',''' + rtrim(t) + '''' from test3    exec(@s)    exec('drop table test3')    fetch next from t_cursor into @nameendclose t_cursordeallocate t_cursor--查看行列互换处理结果select * from test1select * from test2--删除表drop table test1drop table test2----------------------------------------/*固定的写法:*/select t1.* , t2.y , t3.z from(select a = 'b' , x = b from test1 where a = 'x') t1, (select a = 'b' , y = b from test1 where a = 'y') t2,(select a = 'b' , z = b from test1 where a = 'z') t3where t1.a = t2.a and t1.a = t2.aunion allselect t1.* , t2.y , t3.z from(select a = 'c' , x = c from test1 where a = 'x') t1, (select a = 'c' , y = c from test1 where a = 'y') t2,(select a = 'c' , z = c from test1 where a = 'z') t3where t1.a = t2.a and t1.a = t2.aunion allselect t1.* , t2.y , t3.z from(select a = 'd' , x = d from test1 where a = 'x') t1, (select a = 'd' , y = d from test1 where a = 'y') t2,(select a = 'd' , z = d from test1 where a = 'z') t3where t1.a = t2.a and t1.a = t2.aunion allselect t1.* , t2.y , t3.z from(select a = 'e' , x = e from test1 where a = 'x') t1, (select a = 'e' , y = e from test1 where a = 'y') t2,(select a = 'e' , z = e from test1 where a = 'z') t3where t1.a = t2.a and t1.a = t2.a----------------------------------------/*表tb,数据如下:项目种类  业绩  提成洗吹类  200   10外卖      100   5合计      300   15转换成:项目种类  洗吹类  外卖  合计业绩      200     100   300提成      10      5     15*/create table tb(  项目种类 varchar(10),  业绩     int,  提成     int)insert into tb(项目种类,业绩,提成) values('洗吹类',200,10)insert into tb(项目种类,业绩,提成) values('外卖'  ,100,5)insert into tb(项目种类,业绩,提成) values('合计'  ,300,15)goselect 项目种类,sum(洗吹类) as 洗吹类 , sum(外卖) as 外卖 , sum(合计) as 合计 from(  select 项目种类 = '业绩',         洗吹类   = case when 项目种类 = '洗吹类' then 业绩 else 0 end,         外卖     = case when 项目种类 = '外卖'   then 业绩 else 0 end,         合计     = case when 项目种类 = '合计'   then 业绩 else 0 end  from tbunion all  select 项目种类 = '提成' ,         洗吹类   = case when 项目种类 = '洗吹类' then 提成 else 0 end,         外卖     = case when 项目种类 = '外卖'   then 提成 else 0 end,         合计     = case when 项目种类 = '合计'   then 提成 else 0 end  from tb) mgroup by 项目种类order by 项目种类 descdrop table tb/*项目种类 洗吹类      外卖        合计          -------- ----------- ----------- ----------- 业绩     200         100         300提成     10          5           15(所影响的行数为 2 行)*/--------------------------------------/*数据库中tb表格如下 月份    工资   福利  奖金1月     100    200   3002月     110    210   3103月     120    220   3204月     130    230   330我想得到的结果是项目   1月    2月  3月  4月工资   100    110  120  130福利   200    210  220  230奖金   300    310  320  330就是说完全把表格的行列颠倒,有点像那种旋转矩阵,请问如何用sql 语句实现?*/if exists (select * from dbo.sysobjectswhere id = object_id(N'[dbo].[p_zj]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)drop procedure [dbo].[p_zj]GO/*--行列互换的通用存储过程(原著:邹建):将指定的表,按指定的字段进行行列互换*/create proc p_zj       @tbname sysname, --要处理的表名       @fdname sysname, --做为转换的列名       @new_fdname sysname='' --为转换后的列指定列名asdeclare @s1 varchar(8000) , @s2 varchar(8000),        @s3 varchar(8000) , @s4 varchar(8000),        @s5 varchar(8000) , @i varchar(10)select @s1 = '' , @s2 = '' , @s3 = '' , @s4 = '' , @s5 = '' , @i = '0'select @s1 = @s1 + ',@' + @i + ' varchar(8000)',       @s2 = @s2 + ',@' + @i + '=''' + case isnull(@new_fdname , '') when '' then ''       else @new_fdname + '=' end + '''''' + name + '''''''',       @s3 = @s3 + 'select @' + @i + '=@' + @i + '+'',['' + [' + @fdname +        ']+'']=''+cast([' + name + '] as varchar) from [' + @tbname + ']',       @s4 = @s4 + ',@' + @i + '=''select ''+@' + @i,       @s5 = @s5 + '+'' union all ''+@' + @i,       @i=cast(@i as int)+1from syscolumnswhere object_id(@tbname)=id and name<>@fdnameselect @s1=substring(@s1,2,8000),       @s2=substring(@s2,2,8000),       @s4=substring(@s4,2,8000),       @s5=substring(@s5,16,8000)exec('declare ' + @s1 + 'select ' + @s2 + @s3 + 'select ' + @s4 + 'exec(' + @s5 + ')')go--用上面的存储过程测试:create table Test(月份 varchar(4), 工资 int, 福利 int, 奖金 int)insert Test select '1月',100,200,300 union allselect '2月',110,210,310 union allselect '3月',120,220,320 union allselect '4月',130,230,330goexec p_zj 'Test', '月份' , '项目'drop table Testdrop proc p_zj/*项目   1月         2月         3月         4月          ---- ----------- ----------- ----------- ----------- 福利   200         210         220         230工资   100         110         120         130奖金   300         310         320         330(所影响的行数为 3 行)*//*静态写法(SQL2005)*/--测试环境create table Test(月份 varchar(4), 工资 int, 福利 int, 奖金 int)insert Testselect '1月',100,200,300 union allselect '2月',110,210,310 union allselect '3月',120,220,320 union allselect '4月',130,230,330go--测试语句SELECT * FROM (  SELECT 考核月份,月份,金额 FROM      (SELECT 月份, 工资, 福利, 奖金 FROM Test) p  UNPIVOT     (金额 FOR 考核月份 IN (工资, 福利, 奖金))AS unpvt) TPIVOT(MAX(金额)  FOR 月份 in ([1月],[2月],[3月],[4月]))AS pt--测试结果/*考核月份  1月     2月      3月     4月-------  -----  -----   ------  -------福利200210220230工资100110120130奖金300310320330*/--删除环境Drop table Test
  相关解决方案