Problem in string concatenation in sql server using FOR XML Path.
I have the below data
UniqueID ID data
1 1 a
2 1 2
3 1 b
4 1 1
5 2 d
6 2 3
7 2 r
The expected output being
ID ConcatData
1 a,-,-,b,-
2 d,-,-,-,r
What we have to do is that, the number of numeric charecters has to be replaced with those many dashes('-') and then we need to merge the data for the respective id's.
I am using the below query so far
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
开发者_StackOverflow社区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
But the output is
ID ConcatData
1 a,b,-,-,-,
2 d,r,-,-,-,
That is I am not able to position the dashes('-') in between the characters.
Please help
Try this:
;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
Works for the sample data bove and might be a bit quicker than using cursors
Following is the table creating
Create table #temp
(
IDUnique int Identity(1,1),
ID int,
data varchar(100)
)
Following are the records suggested by you.
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')
Following is the cursor implementation
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
here is the Final Result set
精彩评论