SQLServer,多行中的一列根据条件合并为一行中的一列,用SQL怎么做

时间:2021-12-21 02:45:03
需求 
比如有两张表 
一张表为候选人列表 
No UserName 
1  张三 
2  李四 

另一张表为候选人评论 
Id(自增主键)  No  Text 
1            1  test1 
2            1  test2 
3            1  test3 
4            1  test2
5            2  test4 
6            2  test5 

结果 
No UserName Text 
1  张三    test1,test2,test3 
2  李四    test4,test5

注意红色部份,有条件的合并

13 个解决方案

#1


字符串合并,又是这个问题==先

#2


/*
标题:按某字段合并字符串之一(简单合并)
作者:爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开)
时间:2008-11-06
地点:广东深圳

描述:将如下形式的数据按id字段合并value字段。
id    value
----- ------
1     aa
1     bb
2     aaa
2     bbb
2     ccc
需要得到结果:
id     value
------ -----------
1      aa,bb
2      aaa,bbb,ccc
即:group by id, 求 value 的和(字符串相加)
*/
--1、sql2000中只能用自定义的函数解决
create table tb(id int, value varchar(10))
insert into tb values(1, 'aa')
insert into tb values(1, 'bb')
insert into tb values(2, 'aaa')
insert into tb values(2, 'bbb')
insert into tb values(2, 'ccc')
go

create function dbo.f_str(@id int) returns varchar(100)
as
begin
    declare @str varchar(1000)
    set @str = ''
    select @str = @str + ',' + cast(value as varchar) from tb where id = @id
    set @str = right(@str , len(@str) - 1)
    return @str
end
go

--调用函数
select id , value = dbo.f_str(id) from tb group by id

drop function dbo.f_str
drop table tb


--2、sql2005中的方法
create table tb(id int, value varchar(10))
insert into tb values(1, 'aa')
insert into tb values(1, 'bb')
insert into tb values(2, 'aaa')
insert into tb values(2, 'bbb')
insert into tb values(2, 'ccc')
go

select id, [value] = stuff((select ',' + [value] from tb t where id = tb.id for xml path('')) , 1 , 1 , '')
from tb
group by id

drop table tb


--3、使用游标合并数据
create table tb(id int, value varchar(10))
insert into tb values(1, 'aa')
insert into tb values(1, 'bb')
insert into tb values(2, 'aaa')
insert into tb values(2, 'bbb')
insert into tb values(2, 'ccc')
go
declare @t table(id int,value varchar(100))--定义结果集表变量
--定义游标并进行合并处理
declare my_cursor cursor local for
select id , value from tb
declare @id_old int , @id int , @value varchar(10) , @s varchar(100)
open my_cursor
fetch my_cursor into @id , @value
select @id_old = @id , @s=''
while @@FETCH_STATUS = 0
begin
    if @id = @id_old
       select @s = @s + ',' + cast(@value as varchar)
    else
      begin
        insert @t values(@id_old , stuff(@s,1,1,''))
        select @s = ',' + cast(@value as varchar) , @id_old = @id
      end
    fetch my_cursor into @id , @value
END
insert @t values(@id_old , stuff(@s,1,1,''))
close my_cursor
deallocate my_cursor

select * from @t
drop table tb

#3


create function f_str(@NO int)
returns varchar(100)
as
begin
    declare @s varchar(1000)
    select @s = isnull(@s+',','')+text from (select distinct text from ta where no = @no) a
    return @s
end
go
select no,dbo.f_str(no)
from ta
group by no

#4


龟,不要让小梁看到呀

#5


select a.no, a.username, b.text into # from tb1 a join tb2 b

declare @no int, @text varchar(8000)
set @text = ''
update # set @text = case when @no = no then @text + ',' + text else text end,
  text = @text, @no = no
select no, username, max(text) from # group by no

#6


select a.no, a.username, b.text into # from tb1 a join tb2 b

declare @no int, @text varchar(8000)
set @text = ''
update # set @text = case when @no = no then @text + ',' + text else text end,
  text = @text, @no = no
select no, username, max(text) from # group by no, username

#7


if OBJECT_ID('tb1') is not null drop table tb1
go
create table tb1(No int,UserName nvarchar(20))
go
insert tb1
select
1, '张三' union all select
2 , '李四'  

if OBJECT_ID('tb2') is not null drop table tb2
go
create table tb2(id int ,No int,Text nvarchar(20))
go
insert tb2
select
1,            1 , 'test1'   union all select
2 ,           1 , 'test2' union all select
3  ,          1 , 'test3' union all select
4   ,         1 , 'test2' union all select
5    ,        2,  'test4' union all select
6     ,       2,  'test5' 


if object_id('f_tb') is not null drop function f_tb
go
  create function f_tb(@a nvarchar(100))
    returns nvarchar(4000)
    as
   begin
     declare @sql nvarchar(4000)
     set @sql=N''
          select @sql=@sql+N','+text from tb2 where no=@a
     set @sql=stuff(@sql,1,1,N'')
     return(@sql)
   end
go


select a.*,dbo.f_tb(a.no) as 结果 
  from tb1 a,tb2 b where a.No=b.No
  group by a.No,a.UserName
  
  /*
  No UserName 结果
1 张三 test1,test2,test3,test2
2 李四 test4,test5
*/

#8


create table A(No int,UserName varchar(10))
insert into a values(1 , '张三') 
insert into a values(2 , '李四') 
create table b(Id int,  [No] int, [Text] varchar(10)) 
insert into b values(1 ,           1 , 'test1') 
insert into b values(2 ,           1 , 'test2') 
insert into b values(3 ,           1 , 'test3') 
insert into b values(4 ,           1 , 'test2') 
insert into b values(5 ,           2 , 'test4') 
insert into b values(6 ,           2 , 'test5')
go


create function dbo.f_str(@No int) returns varchar(100)
as
begin
    declare @str varchar(1000)
    set @str = ''
    select @str = @str + ',' + cast([Text] as varchar) from (select distinct [no],[text] from b) t where [No] = @No
    set @str = right(@str , len(@str) - 1)
    return @str
end
go

--调用函数
select a.no , t.[text] from a , 
(select [No] , [Text] = dbo.f_str([No]) from (select distinct [no],[text] from b) t group by [No]) t
where a.no = t.[no]

drop function dbo.f_str

drop table a , b

/*
no          text                                                                                                 
----------- ---------------------------------------------------------------------------------------------------- 
1           test1,test2,test3
2           test4,test5

(所影响的行数为 2 行)

*/

#9


IF NOT OBJECT_ID('[tb]') IS NULL
    DROP TABLE [tb]
GO
CREATE TABLE [tb]([FID] INT,[FNAME] NVARCHAR(10))
INSERT [tb]
SELECT 1,'A' UNION ALL
SELECT 2,'B' UNION ALL
SELECT 3,'C' UNION ALL
SELECT 3,'D' UNION ALL
SELECT 3,'E' UNION ALL
SELECT 4,'F'
GO
 

DECLARE @t TABLE(ID INT IDENTITY,FID INT,FNAME NVARCHAR(10))
DECLARE @FID INT,@FNAME NVARCHAR(10)
DECLARE c CURSOR FOR 
     SELECT FID,FNAME FROM tb t WHERE EXISTS(SELECT 1 FROM tb WHERE FID=t.FID AND FName<>t.FNAME)
OPEN c
FETCH NEXT FROM c INTO @FID,@FNAME
WHILE @@FETCH_STATUS=0
BEGIN
    INSERT @t SELECT FID,FNAME FROM TB WHERE LTRIM(FID)+FNAME<>LTRIM(@FID)+@FNAME ORDER BY FID
   
    INSERT @t SELECT @FID,@FNAME
    FETCH NEXT FROM c INTO @FID,@FNAME
END
CLOSE c
DEALLOCATE c
SELECT '方案'+LTRIM((ID-1)/6+1) AS ID,(ID-1)%6+1 AS AID,FNAME FROM @t ORDER BY ID,FID









if OBJECT_ID('tb1') is not null drop table tb1
go
create table tb1(No int,UserName nvarchar(20))
go
insert tb1
select
1, '张三' union all select
2 , '李四'  

if OBJECT_ID('tb2') is not null drop table tb2
go
create table tb2(id int ,No int,Text nvarchar(20))
go
insert tb2
select
1,            1 , 'test1'   union all select
2 ,           1 , 'test2' union all select
3  ,          1 , 'test3' union all select
4   ,         1 , 'test2' union all select
5    ,        2,  'test4' union all select
6     ,       2,  'test5' 


select tb1.No,UserName,[Text]  from tb1 join
(

select No, [Text] = stuff((select ',' + [Text] from (select distinct NO,Text from tb2) m  where No = t.[No] for xml path('')) , 1 , 1 , '')
from (select distinct NO,Text from tb2) t
group by [No]
) m on tb1.no=m.no
/*
No          UserName             Text
----------- -------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1           张三                   test1,test2,test3
2           李四                   test4,test5

(2 行受影响)


*/

#10


谢谢大家了

#11


不好意思各位,需求有点变更,大家请看一下



需求 
比如有两张表 
一张表为候选人列表 
No UserName 
1  张三 
2  李四 

另一张表为候选人评论 
Id(自增主键)  No  Text   description
1            1  test1   desc1
2            1  test2   desc1 
3            1  test3   desc2
4            1  test2   desc3
5            2  test4   desc4
6            2  test5   desc4

结果 
No UserName Text               description
1  张三    test1,test2,test3    desc1,desc2,desc3
2  李四    test4,test5          desc

新增了一列,另外,不想用游标,因为量太大,会影响效率

#12


create table A(No int,UserName varchar(10))
insert into a values(1 , '张三') 
insert into a values(2 , '李四') 
create table b(Id int,  [No] int, [Text] varchar(10),[description] varchar(10)) 
insert into b values(1 ,           1 , 'test1','desc1' ) 
insert into b values(2 ,           1 , 'test2','desc1' ) 
insert into b values(3 ,           1 , 'test3','desc2') 
insert into b values(4 ,           1 , 'test2','desc3') 
insert into b values(5 ,           2 , 'test4','desc4') 
insert into b values(6 ,           2 , 'test5','desc4')
go


create function dbo.f_str1(@No int) returns varchar(100)
as
begin
    declare @str varchar(1000)
    set @str = ''
    select @str = @str + ',' + cast([Text] as varchar) from (select distinct [no],[text] from b) t where [No] = @No
    set @str = right(@str , len(@str) - 1)
    return @str
end
go

create function dbo.f_str2(@No int) returns varchar(100)
as
begin
    declare @str varchar(1000)
    set @str = ''
    select @str = @str + ',' + cast([description] as varchar) from (select distinct [no],[description] from b) t where [No] = @No
    set @str = right(@str , len(@str) - 1)
    return @str
end
go

--调用函数
select a.no , m1.[text] ,m2.[description] from a , 
(select [No] , [Text] = dbo.f_str1([No]) from (select distinct [no],[text] from b) t1 group by [No]) m1,
(select [No] , [description] = dbo.f_str2([No]) from (select distinct [no],[description] from b) t2 group by [No]) m2
where a.no = m1.[no] and a.no = m2.no

drop function dbo.f_str1,dbo.f_str2

drop table a , b

/*
no          text                                                                                                 description                                                                                          
----------- ---------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- 
1           test1,test2,test3                                                                                    desc1,desc2,desc3
2           test4,test5                                                                                          desc4

(所影响的行数为 2 行)


*/

#13


SQLServer,多行中的一列根据条件合并为一行中的一列,用SQL怎么做

#1


字符串合并,又是这个问题==先

#2


/*
标题:按某字段合并字符串之一(简单合并)
作者:爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开)
时间:2008-11-06
地点:广东深圳

描述:将如下形式的数据按id字段合并value字段。
id    value
----- ------
1     aa
1     bb
2     aaa
2     bbb
2     ccc
需要得到结果:
id     value
------ -----------
1      aa,bb
2      aaa,bbb,ccc
即:group by id, 求 value 的和(字符串相加)
*/
--1、sql2000中只能用自定义的函数解决
create table tb(id int, value varchar(10))
insert into tb values(1, 'aa')
insert into tb values(1, 'bb')
insert into tb values(2, 'aaa')
insert into tb values(2, 'bbb')
insert into tb values(2, 'ccc')
go

create function dbo.f_str(@id int) returns varchar(100)
as
begin
    declare @str varchar(1000)
    set @str = ''
    select @str = @str + ',' + cast(value as varchar) from tb where id = @id
    set @str = right(@str , len(@str) - 1)
    return @str
end
go

--调用函数
select id , value = dbo.f_str(id) from tb group by id

drop function dbo.f_str
drop table tb


--2、sql2005中的方法
create table tb(id int, value varchar(10))
insert into tb values(1, 'aa')
insert into tb values(1, 'bb')
insert into tb values(2, 'aaa')
insert into tb values(2, 'bbb')
insert into tb values(2, 'ccc')
go

select id, [value] = stuff((select ',' + [value] from tb t where id = tb.id for xml path('')) , 1 , 1 , '')
from tb
group by id

drop table tb


--3、使用游标合并数据
create table tb(id int, value varchar(10))
insert into tb values(1, 'aa')
insert into tb values(1, 'bb')
insert into tb values(2, 'aaa')
insert into tb values(2, 'bbb')
insert into tb values(2, 'ccc')
go
declare @t table(id int,value varchar(100))--定义结果集表变量
--定义游标并进行合并处理
declare my_cursor cursor local for
select id , value from tb
declare @id_old int , @id int , @value varchar(10) , @s varchar(100)
open my_cursor
fetch my_cursor into @id , @value
select @id_old = @id , @s=''
while @@FETCH_STATUS = 0
begin
    if @id = @id_old
       select @s = @s + ',' + cast(@value as varchar)
    else
      begin
        insert @t values(@id_old , stuff(@s,1,1,''))
        select @s = ',' + cast(@value as varchar) , @id_old = @id
      end
    fetch my_cursor into @id , @value
END
insert @t values(@id_old , stuff(@s,1,1,''))
close my_cursor
deallocate my_cursor

select * from @t
drop table tb

#3


create function f_str(@NO int)
returns varchar(100)
as
begin
    declare @s varchar(1000)
    select @s = isnull(@s+',','')+text from (select distinct text from ta where no = @no) a
    return @s
end
go
select no,dbo.f_str(no)
from ta
group by no

#4


龟,不要让小梁看到呀

#5


select a.no, a.username, b.text into # from tb1 a join tb2 b

declare @no int, @text varchar(8000)
set @text = ''
update # set @text = case when @no = no then @text + ',' + text else text end,
  text = @text, @no = no
select no, username, max(text) from # group by no

#6


select a.no, a.username, b.text into # from tb1 a join tb2 b

declare @no int, @text varchar(8000)
set @text = ''
update # set @text = case when @no = no then @text + ',' + text else text end,
  text = @text, @no = no
select no, username, max(text) from # group by no, username

#7


if OBJECT_ID('tb1') is not null drop table tb1
go
create table tb1(No int,UserName nvarchar(20))
go
insert tb1
select
1, '张三' union all select
2 , '李四'  

if OBJECT_ID('tb2') is not null drop table tb2
go
create table tb2(id int ,No int,Text nvarchar(20))
go
insert tb2
select
1,            1 , 'test1'   union all select
2 ,           1 , 'test2' union all select
3  ,          1 , 'test3' union all select
4   ,         1 , 'test2' union all select
5    ,        2,  'test4' union all select
6     ,       2,  'test5' 


if object_id('f_tb') is not null drop function f_tb
go
  create function f_tb(@a nvarchar(100))
    returns nvarchar(4000)
    as
   begin
     declare @sql nvarchar(4000)
     set @sql=N''
          select @sql=@sql+N','+text from tb2 where no=@a
     set @sql=stuff(@sql,1,1,N'')
     return(@sql)
   end
go


select a.*,dbo.f_tb(a.no) as 结果 
  from tb1 a,tb2 b where a.No=b.No
  group by a.No,a.UserName
  
  /*
  No UserName 结果
1 张三 test1,test2,test3,test2
2 李四 test4,test5
*/

#8


create table A(No int,UserName varchar(10))
insert into a values(1 , '张三') 
insert into a values(2 , '李四') 
create table b(Id int,  [No] int, [Text] varchar(10)) 
insert into b values(1 ,           1 , 'test1') 
insert into b values(2 ,           1 , 'test2') 
insert into b values(3 ,           1 , 'test3') 
insert into b values(4 ,           1 , 'test2') 
insert into b values(5 ,           2 , 'test4') 
insert into b values(6 ,           2 , 'test5')
go


create function dbo.f_str(@No int) returns varchar(100)
as
begin
    declare @str varchar(1000)
    set @str = ''
    select @str = @str + ',' + cast([Text] as varchar) from (select distinct [no],[text] from b) t where [No] = @No
    set @str = right(@str , len(@str) - 1)
    return @str
end
go

--调用函数
select a.no , t.[text] from a , 
(select [No] , [Text] = dbo.f_str([No]) from (select distinct [no],[text] from b) t group by [No]) t
where a.no = t.[no]

drop function dbo.f_str

drop table a , b

/*
no          text                                                                                                 
----------- ---------------------------------------------------------------------------------------------------- 
1           test1,test2,test3
2           test4,test5

(所影响的行数为 2 行)

*/

#9


IF NOT OBJECT_ID('[tb]') IS NULL
    DROP TABLE [tb]
GO
CREATE TABLE [tb]([FID] INT,[FNAME] NVARCHAR(10))
INSERT [tb]
SELECT 1,'A' UNION ALL
SELECT 2,'B' UNION ALL
SELECT 3,'C' UNION ALL
SELECT 3,'D' UNION ALL
SELECT 3,'E' UNION ALL
SELECT 4,'F'
GO
 

DECLARE @t TABLE(ID INT IDENTITY,FID INT,FNAME NVARCHAR(10))
DECLARE @FID INT,@FNAME NVARCHAR(10)
DECLARE c CURSOR FOR 
     SELECT FID,FNAME FROM tb t WHERE EXISTS(SELECT 1 FROM tb WHERE FID=t.FID AND FName<>t.FNAME)
OPEN c
FETCH NEXT FROM c INTO @FID,@FNAME
WHILE @@FETCH_STATUS=0
BEGIN
    INSERT @t SELECT FID,FNAME FROM TB WHERE LTRIM(FID)+FNAME<>LTRIM(@FID)+@FNAME ORDER BY FID
   
    INSERT @t SELECT @FID,@FNAME
    FETCH NEXT FROM c INTO @FID,@FNAME
END
CLOSE c
DEALLOCATE c
SELECT '方案'+LTRIM((ID-1)/6+1) AS ID,(ID-1)%6+1 AS AID,FNAME FROM @t ORDER BY ID,FID









if OBJECT_ID('tb1') is not null drop table tb1
go
create table tb1(No int,UserName nvarchar(20))
go
insert tb1
select
1, '张三' union all select
2 , '李四'  

if OBJECT_ID('tb2') is not null drop table tb2
go
create table tb2(id int ,No int,Text nvarchar(20))
go
insert tb2
select
1,            1 , 'test1'   union all select
2 ,           1 , 'test2' union all select
3  ,          1 , 'test3' union all select
4   ,         1 , 'test2' union all select
5    ,        2,  'test4' union all select
6     ,       2,  'test5' 


select tb1.No,UserName,[Text]  from tb1 join
(

select No, [Text] = stuff((select ',' + [Text] from (select distinct NO,Text from tb2) m  where No = t.[No] for xml path('')) , 1 , 1 , '')
from (select distinct NO,Text from tb2) t
group by [No]
) m on tb1.no=m.no
/*
No          UserName             Text
----------- -------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1           张三                   test1,test2,test3
2           李四                   test4,test5

(2 行受影响)


*/

#10


谢谢大家了

#11


不好意思各位,需求有点变更,大家请看一下



需求 
比如有两张表 
一张表为候选人列表 
No UserName 
1  张三 
2  李四 

另一张表为候选人评论 
Id(自增主键)  No  Text   description
1            1  test1   desc1
2            1  test2   desc1 
3            1  test3   desc2
4            1  test2   desc3
5            2  test4   desc4
6            2  test5   desc4

结果 
No UserName Text               description
1  张三    test1,test2,test3    desc1,desc2,desc3
2  李四    test4,test5          desc

新增了一列,另外,不想用游标,因为量太大,会影响效率

#12


create table A(No int,UserName varchar(10))
insert into a values(1 , '张三') 
insert into a values(2 , '李四') 
create table b(Id int,  [No] int, [Text] varchar(10),[description] varchar(10)) 
insert into b values(1 ,           1 , 'test1','desc1' ) 
insert into b values(2 ,           1 , 'test2','desc1' ) 
insert into b values(3 ,           1 , 'test3','desc2') 
insert into b values(4 ,           1 , 'test2','desc3') 
insert into b values(5 ,           2 , 'test4','desc4') 
insert into b values(6 ,           2 , 'test5','desc4')
go


create function dbo.f_str1(@No int) returns varchar(100)
as
begin
    declare @str varchar(1000)
    set @str = ''
    select @str = @str + ',' + cast([Text] as varchar) from (select distinct [no],[text] from b) t where [No] = @No
    set @str = right(@str , len(@str) - 1)
    return @str
end
go

create function dbo.f_str2(@No int) returns varchar(100)
as
begin
    declare @str varchar(1000)
    set @str = ''
    select @str = @str + ',' + cast([description] as varchar) from (select distinct [no],[description] from b) t where [No] = @No
    set @str = right(@str , len(@str) - 1)
    return @str
end
go

--调用函数
select a.no , m1.[text] ,m2.[description] from a , 
(select [No] , [Text] = dbo.f_str1([No]) from (select distinct [no],[text] from b) t1 group by [No]) m1,
(select [No] , [description] = dbo.f_str2([No]) from (select distinct [no],[description] from b) t2 group by [No]) m2
where a.no = m1.[no] and a.no = m2.no

drop function dbo.f_str1,dbo.f_str2

drop table a , b

/*
no          text                                                                                                 description                                                                                          
----------- ---------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------- 
1           test1,test2,test3                                                                                    desc1,desc2,desc3
2           test4,test5                                                                                          desc4

(所影响的行数为 2 行)


*/

#13


SQLServer,多行中的一列根据条件合并为一行中的一列,用SQL怎么做