временная таблица и курсор на ум ...
Уважаемые Downvoters: временная таблица и курсор должны быть по крайней мере такими же эффективными, как решения с рекурсивными запросами и пользовательскими функциями, принятые выше. Избавьтесь от страха перед курсорами, иногда они являются наиболее эффективным решением. Иногда они являются единственным решением. Смирись с этим.
РЕДАКТИРОВАТЬ: решение на основе курсора ниже. Обратите внимание, что он не имеет никаких ограничений для некурсорных (и более сложных) решений, предложенных в других местах, и производительность, вероятно, примерно такая же (трудно сказать из таблицы из шести строк, конечно).
и, пожалуйста, не оставляйте основную для каждого конструкцию sql только потому, что какой-то блогер говорит "это плохо"; Используй собственное суждение и здравый смысл. Я избегаю курсоров всякий раз, когда это возможно, но не до такой степени, что решение не является надежным.
--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