Reputation: 2501
How can I concatenate a specific attribute of all elements together using SQL XQuery?
I have a table like this:
InvoiceId Details
--------- -----------------------------------------------------------------
1001 <Stuff Id="101" p="3" q="5"/><Stuff Id="102" q="4"/><Stuff Id="103"/>
1002 <Stuff Id="201" /><Stuff Id="202" q="2"/>
and need this result =>
InvoiceId IdDetails
--------- ---------------------
1001 101,102,103
1002 201,202
Upvotes: 2
Views: 1270
Reputation: 394
Perhaps a nicer way is to use the query function in the xml processing instead of a subselect and stuff. Building on Mikael Eriksson's answer, I found the following from this question to be quicker and more concise/readble:
declare @T table(InvoiceId int, Details xml)
insert into @T
select 1001, '<Stuff Id="101" p="3" q="5"/><Stuff Id="102" q="4"/><Stuff Id="103"/>' union all
select 1002, '<Stuff Id="201"/><Stuff Id="202" q="2"/>'
select InvoiceId,
t.n.query('for $i in Stuff return concat($i/@Id, ",")').value('.', 'nvarchar(max)')
from @T
cross apply Details.nodes('.') as t(n)
However, the resulting strings include delimiting spaces and a terminating comma.
Upvotes: 0
Reputation: 138980
declare @T table(InvoiceId int, Details xml)
insert into @T
select 1001, '<Stuff Id="101" p="3" q="5"/><Stuff Id="102" q="4"/><Stuff Id="103"/>' union all
select 1002, '<Stuff Id="201"/><Stuff Id="202" q="2"/>'
select InvoiceId,
stuff((select ','+t.n.value('@Id', 'varchar(10)')
from Details.nodes('Stuff') as t(n)
for xml path('')), 1, 1, '') as IdDetails
from @T
Only unique values for Id
.
select InvoiceId,
stuff((select ','+s.id
from Details.nodes('Stuff') as t(n)
cross apply (select t.n.value('@Id', 'varchar(10)')) as s(id)
group by s.id
for xml path('')), 1, 1, '') as IdDetails
from @T
Upvotes: 2
Reputation: 432421
Simplest way would be to use REPLACE.
SELECT
InvoiceId,
SUBSTRING(
REPLACE(
REPLACE(
CAST(Details AS nvarchar(max))
, '<Stuff Id="', ',')
, '"/>', '')
,2, 2000000000)
FROM
MyTable
Upvotes: 2