如何在T-SQL中执行折叠操作?

5
如果我的数据格式如下:
 id    subid      text
 1     1          Hello
 1     2          World
 1     3          !
 2     1          B
 2     2          B
 2     3          Q

And would like it in this format:

 id  fold
 1   HelloWorld!
 2   BBQ

我该如何在T-SQL中实现它?
4个回答

10

1
哇,那些例子真是太强了。 - StingyJack
我不确定你所说的“intense”的意思是什么。 - LeppyR64
貌似非常复杂和抽象。 - StingyJack
同意。然而,这就是为什么我建议不要在 T-SQL 中处理它,而是在应用程序层处理。 - LeppyR64

2

我会想到一个临时表和游标...

亲爱的Downvoters:临时表和游标至少与上面接受的递归查询和自定义函数解决方案一样有效。克服你们对游标的恐惧,有时它们是最有效的解决方案。有时它们是唯一的解决方案。接受现实。

编辑:下面是基于游标的解决方案。请注意,它没有其他地方提出的非游标(更复杂)解决方案的任何限制,并且性能可能大致相同(当然从一个六行表中很难判断)。

而且,请不要因为某个博主说“它很糟糕”而放弃SQL的主要for-each结构;要运用自己的判断力和常识。我尽可能避免使用游标,但不至于使解决方案不健壮。

--initial data table
create table #tmp (
    id int,
    subid int,
    txt varchar(256)
)

--populate with sample data from original question
insert into #tmp (id,subid,txt) values (1, 1, 'Hello')
insert into #tmp (id,subid,txt) values (1, 2, 'World')
insert into #tmp (id,subid,txt) values (1, 3, '!')
insert into #tmp (id,subid,txt) values (2, 1, 'B')
insert into #tmp (id,subid,txt) values (2, 2, 'B')
insert into #tmp (id,subid,txt) values (2, 3, 'Q')

--temp table for grouping results
create table #tmpgrp (
    id int,
    txt varchar(4000)
)

--cursor for looping through data
declare cur cursor local for
    select id, subid, txt from #tmp order by id, subid

declare @id int
declare @subid int
declare @txt varchar(256)

declare @curid int
declare @curtxt varchar(4000)


open cur

fetch next from cur into @id, @subid, @txt

set @curid = @id
set @curtxt = ''

while @@FETCH_STATUS = 0 begin
    if @curid <> @id begin
        insert into #tmpgrp (id,txt) values (@curid,@curtxt)
        set @curid = @id
        set @curtxt = ''
    end
    set @curtxt = @curtxt + isnull(@txt,'')
    fetch next from cur into @id, @subid, @txt
end

insert into #tmpgrp (id,txt) values (@curid,@curtxt)

close cur

deallocate cur

--show output
select * from #tmpgrp

--drop temp tables
drop table #tmp
drop table #tmpgrp

@[StingyJack]: 除非它们是唯一有效的解决方案。 - Steven A. Lowe
1
@StingyJack:光标确实有其适用场合。但是,正如所有人所提到的,这不是适当的场所。 - LeppyR64
@StingyJack: 添加了光标解决方案 - Steven A. Lowe
@[Jason Lepack]: 添加了光标解决方案。 - Steven A. Lowe
是的,除非你没有其他选择,否则游标是不好的。我以前曾经不得不使用它们,但我的观点更多的是,如果有可能,应该像瘟疫一样避免它们。你的例子应该声明一个FAST_FORWARD,因为你是只读的,并且只向前移动。 - StingyJack
显示剩余3条评论

1
declare  @tmp table (id int, subid int,txt varchar(256) )  
--populate with sample data from original question 
insert into @tmp (id,subid,txt) values (1, 1, 'Hello') 
insert into @tmp (id,subid,txt) values (1, 2, 'World') 
insert into @tmp (id,subid,txt) values (1, 3, '!') 
insert into @tmp (id,subid,txt) values (2, 1, 'B') 
insert into @tmp (id,subid,txt) values (2, 2, 'B') 
insert into @tmp (id,subid,txt) values (2, 3, 'Q') 

解决方案

Select id, fold = (Select cast(txt as varchar(100)) from @tmp t2 where t1.id = t2.id for xml path(''))
from @tmp t1
group by t1.id

0
将此内容封装在一个函数中以进行单次执行...
DECLARE @returnValue varchar(4000)

SELECT @returnValue = ISNULL(@returnValue + ', ' +  myTable.text, myTable.text)
FROM myTable 

RETURN @returnValue

对于少量记录,这个方法可以工作...但是如果超过5或10条记录,SQL函数就无法胜任了,需要像其他人建议的那样将其移动到应用程序层。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接