Проблема в конкатенации строк на сервере SQL с использованием FOR XML Path. - PullRequest
1 голос
/ 16 июня 2011

У меня есть данные ниже

UniqueID    ID  data
1       1   a
2       1   2
3       1   b
4       1   1
5       2   d
6       2   3
7       2   r

Ожидаемый результат

ID  ConcatData
1   a,-,-,b,-
2   d,-,-,-,r

Что нам нужно сделать, так это то, что число числовых символов должно быть заменено на эти многочисленные тире ('-'), а затем нам нужно объединить данные для соответствующих идентификаторов.

Я пока что пользуюсь приведенным ниже запросом

declare @t table(UniqueID int identity(1,1), ID int, data varchar(10))  
insert into @t select 1, 'a' union all  select 1, '2' union all select 1, 'b' 
union all select 1, '1' union all select 2, 'd' union all select 2, '3' 
union all select 2, 'r' 

select * from @t

;with cte1 as 
(     
    select 
        UniqueId
        , id
        , data
        , case when isnumeric(data) = 1 then cast(data as int) end Level
         from @t     
    union all     
    select 
        UniqueId
        , id
        , CAST('-' as varchar(10))
        , Level - 1     
    from cte1     
    where Level > 0 ) 
,cte2 as
(
select id, GroupID = Dense_Rank() Over(Order by id),data, DataOrder = ROW_NUMBER() over(order by UniqueID, Level)
from cte1 
where Level is null or data = '-' 
) 

SELECT
ID
, (select data + ',' 
from cte2 t2 
where t2.GroupID = t1.GroupID
for XML path('')
) as ConcatData
from cte2 t1
group by t1.ID ,t1.GroupID

Но на выходе получается

ID  ConcatData
1   a,b,-,-,-,
2   d,r,-,-,-,

То есть я не могу расположить тире ('-') между символами.

Пожалуйста, помогите

Ответы [ 2 ]

0 голосов
/ 16 июня 2011

Попробуйте это:

;with cte1 as
(
select 
UniqueId
, id
, data
,case when isnumeric(data) = 1 
    THEN replicate(',-',data) 
    ELSE ',' + data end as string
from @t
)

select 
id
,LTRIM(STUFF(
    (
    SELECT
      ' ' + t2.String
    FROM Cte1 t2
    WHERE t2.id = t1.id
    FOR XML PATH('')
    ), 2, 1, ''
  )) As concatenated_string
from cte1 t1 group by t1.ID ,t1.ID 

Работает для выборки данных и может быть немного быстрее, чем при использовании курсоров

0 голосов
/ 16 июня 2011

Ниже приведена таблица создания

Create table #temp
(
    IDUnique int Identity(1,1),
    ID int, 
    data varchar(100)
)

Ниже приведены записи, предложенные вами.

Insert into #temp(ID, data) Values(1, 'a')
Insert into #temp(ID, data) Values(1, '2')
Insert into #temp(ID, data) Values(1, 'b')
Insert into #temp(ID, data) Values(1, '1')
Insert into #temp(ID, data) Values(2, 'd')
Insert into #temp(ID, data) Values(2, '3')
Insert into #temp(ID, data) Values(2, 'r')

enter image description here

Ниже приведена реализация курсора

declare @IDUnique int
declare @ID int
declare  @data varchar(100)
declare @Latest int
declare @Previous int
declare @Row int

set @Latest = 1
set @Previous = 1

Create Table #temp1
(
    ID int,
    data varchar(100)
)

--SELECT Row_Number() Over(Order by IDUnique) Row, IDUnique, ID, data  From #temp


DECLARE @getAccountID CURSOR SET @getAccountID = CURSOR FOR SELECT Row_Number() Over(Order by IDUnique) Row, IDUnique, ID, data  From #temp
OPEN @getAccountID
FETCH NEXT FROM @getAccountID INTO @Row, @IDUnique, @ID, @data
WHILE @@FETCH_STATUS = 0
BEGIN
    IF(@Row = 1)
    Begin
        Set @Previous = @ID
        Set @Latest = @ID
        Insert into #temp1(ID, data)values(@Previous, @data)
    End
    Else If (@Previous <> @ID)
    Begin
        Set @Previous = @ID
        Set @Latest = @ID
        Insert into #temp1(ID, data)values(@Previous, @data)
    End
    Else
    Begin
        Declare @number int
        if(ISNUMERIC(@data) = 1)
        Begin
            Set @number = Convert(int , @data)
            While(@number <> 0)
            Begin
                Update #temp1 Set Data  = Data + ',-' Where ID = @ID
                Set @number = @number - 1
            End
        End
        Else    
        begin
            Update #temp1 Set Data  = Data + ',' + @data Where ID = @ID
        End
    End

    FETCH NEXT FROM @getAccountID INTO @Row, @IDUnique, @ID, @data
END
CLOSE @getAccountID
DEALLOCATE @getAccountID

Select * from #temp1
Select * from #temp
Drop Table #temp

вот итоговый набор результатов

enter image description here

...