加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

SQL SERVER一列多行转一行的方法详解

(2014-12-16 15:28:52)
标签:

sqlserver多行转一行

sqlserver多行变一行

sql一列多行变一行

sqlserver字符拼接

sql多行合并一行

分类: 数据库学习

一、创建测试表
drop table test
create table test(id int,val varchar(10))

--插入测试值
insert into test
select  1,'aa'
union all
select  1,'bb'
union all
select  1,'cc'
union all
select  2,'dd'
union all
select  3,'ee'
union all
select  3,'ff'
union all
select  4,'aaa'
union all
select  4,'bbb'
union all
select  4,'ccc'
union all
select  4,'ddd'

-- 查询表数据
select * from test
id          val       
----------- ----------
          aa
          bb
          cc
          dd
          ee
          ff
          aaa
          bbb
          ccc
          ddd

--目标数据
id          val       
----------- ----------
    aa,bb,cc
    dd
    ee,ff
    aaa,bbb,ccc,ddd


二、SQL SERVER2000及SQL SERVER2005中实现方法示例
1、通过调用自定义函数实现
--创建函数
create  function fun_test(@[id] int)
returns varchar(100)
as
begin
declare @str varchar(200)
set @str=''
select @str=@str+','+val from test where [id]=@[id]
select @str=right(@str,len(@str)-1)
return @str
end

--调用函数查询
select [id],val=dbo.fun_test([id])
from  test
group by [id]
go
drop function fun_test

运行结果:
id          val                           
----------- ------------------------------
          aa,bb,cc
          dd
          ee,ff
          aaa,bbb,ccc,ddd

 

2、通过游标来处理
declare @tab table(id int,val varchar(30))
declare cur_test cursor for
select  id,val from test order by id,val
declare @id_old int,@id int,@val varchar(20),@s varchar(100)
open cur_test
fetch cur_test into @id,@val
select @id_old=@id,@s=''
while @@fetch_status=0
begin
if @id=@id_old
select  @s=@s+','+@val
else
begin
insert into @tab
select @id_old,stuff(@s,1,1,'')
select  @s=','+@val,@id_old=@id
end
fetch cur_test into @id,@val
end
insert into @tab
select @id_old,stuff(@s,1,1,'')
close cur_test
deallocate cur_test

select * from @tab

运行结果:
id          val                           
----------- ------------------------------
          aa,bb,cc
          dd
          ee,ff
          aaa,bbb,ccc,ddd

 

3、通过临时表实现字符串合并处理
declare @tab table(id int,val varchar(20))
declare @id int,@val varchar(50)
insert into @tab
select id,val
from test
order by id,val

update @tab
set @val=case when @id=id then @val+','+val else val end,
 @id=id,
 val=@val
--select * from @tab
select id,max(val)val,count(*)cnt from @tab group by id

运行结果:
id          val                  cnt        
----------- -------------------- -----------
          aa,bb,cc             3
          dd                   1
          ee,ff                2
          aaa,bbb,ccc,ddd      4

 

4、通过拼接字符串处理

--每组小于等于2条记录时字符合并处理
select id,min(val)+case when count(*)=1 then '' else ','+max(val) end as val
from test
group by id

运行结果:
id          val                  
----------- ---------------------
          aa,cc
          dd
          ee,ff
          aaa,ddd

 

--每组小于等于3条记录时字符合并处理
select id,min(val)
+case when count(*)>=3 then ','+(select top 1 val from test where id=a.id and val not in (min(a.val),max(a.val))) else '' end
+case when count(*)>=2 then ','+max(val) else '' end as val
from test a
group by id

运行结果:
id          val                             
----------- --------------------------------
          aa,bb,cc
          dd
          ee,ff
          aaa,bbb,ddd

 

--每组小于等于4条记录时字符合并处理
select id,min(val)
+case when count(*)=4 then ','+(select top 1 val from test where id=a.id and val not in (min(a.val),max(a.val)) order by val) else '' end
+case when count(*)=4 then ','+(select top 1 val from test where id=a.id and val not in (min(a.val),max(a.val)) order by val desc) else '' end
+case when count(*)=3 then ','+(select val from test where id=a.id and val not in (min(a.val),max(a.val))) else '' end
+case when count(*)>=2 then ','+max(val) else '' end as val
from test a
group by id

运行结果:
id          val                                                   
----------- ------------------------------------------------------
          aa,bb,cc
          dd
          ee,ff
          aaa,bbb,ccc,ddd

注意:该种方法存在一定的局限性,当每组的记录数变化时,需要手动拼接对应的SQL语句处理。如你的需求数据中每组数据多余4条记录时,请采用其他相对灵活的方法处理。

 

5、使用自带函数STUFF()和OUTER APPLY来处理
注意:由于函数OUTER APPLY在SQL SERVER2005及以上版本数据库中才存在,所以下面的方法只适用于SQL SERVER2005及以上。
select *
from 
(
select distinct id
from test
)a
OUTER APPLY
(
select val=stuff(replace(replace((select val from test N where id=a.id for xml auto),'',''),1,1,'')
)b

运行结果:
id          val
----------- -----------------------------------
          aa,bb,cc
          dd
          ee,ff
          aaa,bbb,ccc,ddd

 

6、通过循环生成处理
declare @tab table(id int,val varchar(30))
declare @tab1 table(id int identity(1,1),num int)
insert into @tab1(num)
select distinct id
from test

declare @i_min int,@i_max int,@num int
select @i_min=min(id),@i_max=max(id) from @tab1
while @i_min<<A href="mailto:=@i_max">=@i_max
begin
select @num=num from @tab1 where id=@i_min
declare @str varchar(30)
set  @str=''
select @str=@str+','+val from test where id=@num
--select stuff(@str,1,1,'')
insert into @tab
select @i_min,stuff(@str,1,1,'')

set @i_min=@i_min+1
end
select * from @tab

运行结果:
id          val                           
----------- ------------------------------
          aa,bb,cc
          dd
          ee,ff
          aaa,bbb,ccc,ddd

 


本文参考资料:http://www.360doc.com/content/13/0520/10/1485725_286711747.shtml

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有