I\'ve got the following tables:
EntryTag
---------
EntryID
TagID
Example putput (EntryID, TagID):
1 2
1 4
1 5
2 3
2 4
2 5
e
select ET1.EntryID,
(
select ', '+T.Name
from Tags as T
inner join EntryTag as ET2
on T.TagID = ET2.TagID
where ET1.EntryID = ET2.EntryID
for xml path(''), type
).value('substring(text()[1], 3)', 'varchar(max)') as TagsCommaDelimited
from EntryTag as ET1
group by ET1.EntryID
Dissecting the query
The main query does a group by so you only get one row for each EntryID.
The column TagsCommaDelimited is created with a correlated subquery.
In SQL Server for xml path is used to create a XML representation of a query result. You have good control over how the XML is created by using column aliases and the parameters to path and root.
The concatenated value ', '+T.Name in the corelated subquery will not have a column name and the empty parameter to for xml path('') creates the xml without any tags at all. There will be only one text value returned.
When you add type to a for xml query the data type will be XML.
To get a value out of a XML you should use the value() method. You could cast to a string but if you did that you would for instance get & in the string wherever you have used &.
The first parameter in the value() function is the xQuery expression used to get the value you want. Use text() to specify that you only want the value for the current element. [1] is telling SQL Server that you want the first text node found (you only have one here) but it is still necessary.
The string created by the for xml query has an extra comma and a space at the beginning of the string and that needs to be removed. Here I use the XQuery function substring to get everything but the first two characters.
The second parameter to value() specifies the datatype that should be returned.