I have a column in table T1
named Categories
, which contains GUIDs in XML. I am able to extract the GUIDs in a comma-separated form using the below query.
SELECT Row, ID, Name, City, Category = STUFF( ( SELECT ',' + t.c.value('.', 'nvarchar(max)') FROM dbo.T1 t1 OUTER APPLY t1.Categories.nodes('root/string') as t(c) WHERE t1.ID = t2.ID FOR XML PATH('') ), 1, 1, '' ) FROM dbo.T1 t2
I have another table T2
, which contains the names of the Categories. I now want to use these comma-separated GUIDs to go and fetch their corresponding Name
from T2
.
What changes do I need to make in my SELECT statement to write a LEFT OUTER JOIN which takes this comma-separated GUIDs and returns comma-separated names from T2
.
T2
looks something like this:
Advertisement
Answer
I would join the category name table before concatenating the values to avoid another iteration of splitting and concatenating.
Sample data
create table xmlData ( id int, data xml ); insert into xmlData (id, data) values (1,' <root> <guid>5d8547aa-e1e7-4f69-88a2-655879531582</guid> <guid>78555c5d-e39f-48f3-a148-30161b0fb995</guid> </root> '), (2,' <root> <guid>5d8547aa-e1e7-4f69-88a2-655879531582</guid> <guid>f58177f6-63c8-4985-baa8-2db05248f13f</guid> </root> '), (3,' <root> <guid>5d8547aa-e1e7-4f69-88a2-655879531582</guid> <guid>d8f9b789-6d60-4688-9d91-c0f8b1df5319</guid> </root> '); create table categoryName ( guid uniqueidentifier, name nvarchar(20) ); insert into categoryName (guid, name) values ('5d8547aa-e1e7-4f69-88a2-655879531582', 'Alpha'), ('78555c5d-e39f-48f3-a148-30161b0fb995', 'Beta'), ('f58177f6-63c8-4985-baa8-2db05248f13f', 'Gamma'), ('d8f9b789-6d60-4688-9d91-c0f8b1df5319', 'Delta');
Solution
Two versions because the SQL Server version is not specified in the question tags… The string_agg()
function is available starting from SQL Server 2017.
With string_agg()
select xd.id, string_agg(cn.name, ',') as 'category_names' from xmlData xd cross apply xd.data.nodes('root/guid') g(guid) join categoryName cn on cn.guid = g.guid.value('.', 'nvarchar(36)') group by xd.id order by xd.id;
Without string_agg()
select xd.id, stuff( ( select ',' + cn.name from xmlData xd2 cross apply xd.data.nodes('root/guid') g(guid) join categoryName cn on cn.guid = g.guid.value('.', 'nvarchar(36)') where xd2.id = xd.id for xml path('') ), 1, 1, '' ) as 'category_names' from xmlData xd order by xd.id;
Result
id category_names -- -------------- 1 Alpha,Beta 2 Alpha,Gamma 3 Alpha,Delta
Fiddle to see things in action.