This article covers various ways of concatenating strings in SQL, including an improved version of your code which doesn't XML-encode the concatenated values.
SELECT ID, abc = STUFF
(
(
SELECT ',' + name
FROM temp1 As T2
-- You only want to combine rows for a single ID here:
WHERE T2.ID = T1.ID
ORDER BY name
FOR XML PATH (''), TYPE
).value('.', 'varchar(max)')
, 1, 1, '')
FROM temp1 As T1
GROUP BY id
To understand what's happening, start with the inner query:
SELECT ',' + name
FROM temp1 As T2
WHERE T2.ID = 42 -- Pick a random ID from the table
ORDER BY name
FOR XML PATH (''), TYPE
Because you're specifying FOR XML
, you'll get a single row containing an XML fragment representing all of the rows.
Because you haven't specified a column alias for the first column, each row would be wrapped in an XML element with the name specified in brackets after the FOR XML PATH
. For example, if you had FOR XML PATH ('X')
, you'd get an XML document that looked like:
<X>,aaa</X>
<X>,bbb</X>
...
But, since you haven't specified an element name, you just get a list of values:
,aaa,bbb,...
The .value('.', 'varchar(max)')
simply retrieves the value from the resulting XML fragment, without XML-encoding any "special" characters. You now have a string that looks like:
',aaa,bbb,...'
The STUFF
function then removes the leading comma, giving you a final result that looks like:
'aaa,bbb,...'
It looks quite confusing at first glance, but it does tend to perform quite well compared to some of the other options.