How to concatenate text from multiple rows into a single text string in SQL server?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1663















Consider a database table holding names, with three rows:



Peter
Paul
Mary


Is there an easy way to turn this into a single string of Peter, Paul, Mary?










share|improve this question




















  • 21





    For answers specific to SQL Server, try this question.

    – Matt Hamilton
    Oct 12 '08 at 0:03






  • 14





    For MySQL, check out Group_Concat from this answer

    – Pykler
    May 6 '11 at 19:48








  • 24





    I wish the next version of SQL Server would offer a new feature to solve multi-row string concatination elegantly without the silliness of FOR XML PATH.

    – Pete Alvin
    Oct 2 '14 at 11:47











  • step by step tutorial for describe above answers : try this article : [ sqlmatters.com/Articles/… ]

    – saber tabatabaee yazdi
    Dec 27 '14 at 2:10








  • 3





    Not SQL, but if this is a once-only thing, you can paste the list into this in-browser tool convert.town/column-to-comma-separated-list

    – Stack Man
    May 27 '15 at 7:56


















1663















Consider a database table holding names, with three rows:



Peter
Paul
Mary


Is there an easy way to turn this into a single string of Peter, Paul, Mary?










share|improve this question




















  • 21





    For answers specific to SQL Server, try this question.

    – Matt Hamilton
    Oct 12 '08 at 0:03






  • 14





    For MySQL, check out Group_Concat from this answer

    – Pykler
    May 6 '11 at 19:48








  • 24





    I wish the next version of SQL Server would offer a new feature to solve multi-row string concatination elegantly without the silliness of FOR XML PATH.

    – Pete Alvin
    Oct 2 '14 at 11:47











  • step by step tutorial for describe above answers : try this article : [ sqlmatters.com/Articles/… ]

    – saber tabatabaee yazdi
    Dec 27 '14 at 2:10








  • 3





    Not SQL, but if this is a once-only thing, you can paste the list into this in-browser tool convert.town/column-to-comma-separated-list

    – Stack Man
    May 27 '15 at 7:56














1663












1663








1663


525






Consider a database table holding names, with three rows:



Peter
Paul
Mary


Is there an easy way to turn this into a single string of Peter, Paul, Mary?










share|improve this question
















Consider a database table holding names, with three rows:



Peter
Paul
Mary


Is there an easy way to turn this into a single string of Peter, Paul, Mary?







sql sql-server csv string-concatenation group-concat






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 19 '18 at 20:41









Steve Chambers

22.3k1198146




22.3k1198146










asked Oct 11 '08 at 23:49









JohnnyMJohnnyM

11.1k103035




11.1k103035








  • 21





    For answers specific to SQL Server, try this question.

    – Matt Hamilton
    Oct 12 '08 at 0:03






  • 14





    For MySQL, check out Group_Concat from this answer

    – Pykler
    May 6 '11 at 19:48








  • 24





    I wish the next version of SQL Server would offer a new feature to solve multi-row string concatination elegantly without the silliness of FOR XML PATH.

    – Pete Alvin
    Oct 2 '14 at 11:47











  • step by step tutorial for describe above answers : try this article : [ sqlmatters.com/Articles/… ]

    – saber tabatabaee yazdi
    Dec 27 '14 at 2:10








  • 3





    Not SQL, but if this is a once-only thing, you can paste the list into this in-browser tool convert.town/column-to-comma-separated-list

    – Stack Man
    May 27 '15 at 7:56














  • 21





    For answers specific to SQL Server, try this question.

    – Matt Hamilton
    Oct 12 '08 at 0:03






  • 14





    For MySQL, check out Group_Concat from this answer

    – Pykler
    May 6 '11 at 19:48








  • 24





    I wish the next version of SQL Server would offer a new feature to solve multi-row string concatination elegantly without the silliness of FOR XML PATH.

    – Pete Alvin
    Oct 2 '14 at 11:47











  • step by step tutorial for describe above answers : try this article : [ sqlmatters.com/Articles/… ]

    – saber tabatabaee yazdi
    Dec 27 '14 at 2:10








  • 3





    Not SQL, but if this is a once-only thing, you can paste the list into this in-browser tool convert.town/column-to-comma-separated-list

    – Stack Man
    May 27 '15 at 7:56








21




21





For answers specific to SQL Server, try this question.

– Matt Hamilton
Oct 12 '08 at 0:03





For answers specific to SQL Server, try this question.

– Matt Hamilton
Oct 12 '08 at 0:03




14




14





For MySQL, check out Group_Concat from this answer

– Pykler
May 6 '11 at 19:48







For MySQL, check out Group_Concat from this answer

– Pykler
May 6 '11 at 19:48






24




24





I wish the next version of SQL Server would offer a new feature to solve multi-row string concatination elegantly without the silliness of FOR XML PATH.

– Pete Alvin
Oct 2 '14 at 11:47





I wish the next version of SQL Server would offer a new feature to solve multi-row string concatination elegantly without the silliness of FOR XML PATH.

– Pete Alvin
Oct 2 '14 at 11:47













step by step tutorial for describe above answers : try this article : [ sqlmatters.com/Articles/… ]

– saber tabatabaee yazdi
Dec 27 '14 at 2:10







step by step tutorial for describe above answers : try this article : [ sqlmatters.com/Articles/… ]

– saber tabatabaee yazdi
Dec 27 '14 at 2:10






3




3





Not SQL, but if this is a once-only thing, you can paste the list into this in-browser tool convert.town/column-to-comma-separated-list

– Stack Man
May 27 '15 at 7:56





Not SQL, but if this is a once-only thing, you can paste the list into this in-browser tool convert.town/column-to-comma-separated-list

– Stack Man
May 27 '15 at 7:56












44 Answers
44






active

oldest

votes













1 2
next












1232














If you are on SQL Server 2017 or Azure, see Mathieu Renda answer.



I had a similar issue when I was trying to join two tables with one-to-many relationships. In SQL 2005 I found that XML PATH method can handle the concatenation of the rows very easily.



If there is a table called STUDENTS



SubjectID       StudentName
---------- -------------
1 Mary
1 John
1 Sam
2 Alaina
2 Edward


Result I expected was:



SubjectID       StudentName
---------- -------------
1 Mary, John, Sam
2 Alaina, Edward


I used the following T-SQL:



SELECT Main.SubjectID,
LEFT(Main.Students,Len(Main.Students)-1) As "Students"
FROM
(
SELECT DISTINCT ST2.SubjectID,
(
SELECT ST1.StudentName + ',' AS [text()]
FROM dbo.Students ST1
WHERE ST1.SubjectID = ST2.SubjectID
ORDER BY ST1.SubjectID
FOR XML PATH ('')
) [Students]
FROM dbo.Students ST2
) [Main]


You can do the same thing in a more compact way if you can concat the commas at the beginning and use substring to skip the first one so you don't need to do a sub-query:



SELECT DISTINCT ST2.SubjectID, 
SUBSTRING(
(
SELECT ','+ST1.StudentName AS [text()]
FROM dbo.Students ST1
WHERE ST1.SubjectID = ST2.SubjectID
ORDER BY ST1.SubjectID
FOR XML PATH ('')
), 2, 1000) [Students]
FROM dbo.Students ST2





share|improve this answer





















  • 10





    Great solution. The following may be helpful if you need to handle special characters like those in HTML: Rob Farley: Handling special characters with FOR XML PATH('').

    – user140628
    Apr 17 '13 at 12:35






  • 8





    Apparently this doesn't work if the names contain XML characters such as < or &. See @BenHinman's comment.

    – Sam
    Aug 13 '13 at 1:26






  • 21





    NB: This method is reliant on undocumented behavior of FOR XML PATH (''). That means it should not be considered reliable as any patch or update could alter how this functions. It's basically relying on a deprecated feature.

    – Bacon Bits
    Nov 13 '14 at 18:54






  • 23





    @Whelkaholism The bottom line is that FOR XML is intended to generate XML, not concatenate arbitrary strings. That's why it escapes &, < and > to XML entity codes (&amp;, &lt;, &gt;). I assume it also will escape " and ' to &quot; and &apos; in attributes as well. It's not GROUP_CONCAT(), string_agg(), array_agg(), listagg(), etc. even if you can kind of make it do that. We should be spending our time demanding Microsoft implement a proper function.

    – Bacon Bits
    Mar 23 '15 at 14:15








  • 9





    Good news: MS SQL Server will be adding string_agg in v.Next. and all of this can go away.

    – Jason C
    Apr 6 '17 at 0:32





















942















This answer may return unexpected results when an ORDER BY clause is present. For consistent results, use one of the FOR XML PATH methods detailed in other answers.




Use COALESCE:



DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + Name
FROM People


Just some explanation (since this answer seems to get relatively regular views):




  • Coalesce is really just a helpful cheat that accomplishes two things:


1) No need to initialize @Names with an empty string value.



2) No need to strip off an extra separator at the end.




  • The solution above will give incorrect results if a row has a NULL Name value (if there is a NULL, the NULL will make @Names NULL after that row, and the next row will start over as an empty string again. Easily fixed with one of two solutions:


DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') + Name
FROM People
WHERE Name IS NOT NULL


or:



DECLARE @Names VARCHAR(8000) 
SELECT @Names = COALESCE(@Names + ', ', '') +
ISNULL(Name, 'N/A')
FROM People


Depending on what behavior you want (the first option just filters NULLs out, the second option keeps them in the list with a marker message [replace 'N/A' with whatever is appropriate for you]).






share|improve this answer





















  • 67





    To be clear, coalesce has nothing to do with creating the list, it just makes sure that NULL values are not included.

    – Graeme Perrow
    Feb 13 '09 at 12:02






  • 16





    @Graeme Perrow It doesn't exclude NULL values (a WHERE is required for that -- this will lose results if one of the input values is NULL), and it is required in this approach because: NULL + non-NULL -> NULL and non-NULL + NULL -> NULL; also @Name is NULL by default and, in fact, that property is used as an implicit sentinel here to determine if a ', ' should be added or not.

    – user166390
    Aug 15 '10 at 18:57








  • 58





    Please note that this method of concatenation relies on SQL Server executing the query with a particular plan. I have been caught out using this method (with the addition of an ORDER BY). When it was dealing with a small number of rows it worked fine but with more data SQL Server chose a different plan which resulted in selecting the first item with no concatenation whatsoever. See this article by Anith Sen.

    – fbarber
    Apr 26 '12 at 2:18






  • 14





    This method cannot be used as a sub query in a select list or where-clause, because it use a tSQL variable. In such cases you could use the methods offered by @Ritesh

    – R. Schreurs
    Aug 2 '13 at 8:10






  • 10





    This is not a reliable method of concatenation. It is unsupported and should not be used (per Microsoft, e.g. support.microsoft.com/en-us/kb/287515, connect.microsoft.com/SQLServer/Feedback/Details/704389). It can change without warning. Use the XML PATH technique discussed in stackoverflow.com/questions/5031204/… I wrote more here: marc.durdin.net/2015/07/…

    – Marc Durdin
    Jul 15 '15 at 0:23





















326














One method not yet shown via the XML data() command in MS SQL Server is:



Assume table called NameList with one column called FName,



SELECT FName + ', ' AS 'data()' 
FROM NameList
FOR XML PATH('')


returns:



"Peter, Paul, Mary, "


Only the extra comma must be dealt with.



Edit: As adopted from @NReilingh's comment, you can use the following method to remove the trailing comma. Assuming the same table and column names:



STUFF(REPLACE((SELECT '#!' + LTRIM(RTRIM(FName)) AS 'data()' FROM NameList
FOR XML PATH('')),' #!',', '), 1, 2, '') as Brands





share|improve this answer





















  • 13





    holy s**t thats amazing! When executed on its own, as in your example the result is formatted as a hyperlink, that when clicked (in SSMS) opens a new window containing the data, but when used as part of a larger query it just appears as a string. Is it a string? or is it xml that i need to treat differently in the application that will be using this data?

    – Ben
    Sep 7 '12 at 15:56






  • 8





    This approach also XML-escapes characters like < and >. So, SELECTing '<b>' + FName + '</b>' results in "&lt;b&gt;John&lt;/b&gt;&lt;b&gt;Paul..."

    – Lukáš Lánský
    Feb 26 '14 at 18:34






  • 8





    Neat solution. I am noticing that even when I do not add the + ', ' it still adds a single space between every concatenated element.

    – Baodad
    Oct 3 '14 at 22:40






  • 6





    @Baodad That appears to be part of the deal. You can workaround by replacing on an added token character. For example, this does a perfect comma-delimited list for any length: SELECT STUFF(REPLACE((SELECT '#!'+city AS 'data()' FROM #cityzip FOR XML PATH ('')),' #!',', '),1,2,'')

    – NReilingh
    Feb 29 '16 at 18:12






  • 1





    Wow, actually in my testing using data() and a replace is WAY more performant than not. Super weird.

    – NReilingh
    Feb 29 '16 at 18:33



















265














In SQL Server 2005



SELECT Stuff(
(SELECT N', ' + Name FROM Names FOR XML PATH(''),TYPE)
.value('text()[1]','nvarchar(max)'),1,2,N'')




In SQL Server 2016



you can use the FOR JSON syntax



i.e.



SELECT per.ID,
Emails = JSON_VALUE(
REPLACE(
(SELECT _ = em.Email FROM Email em WHERE em.Person = per.ID FOR JSON PATH)
,'"},{"_":"',', '),'$[0]._'
)
FROM Person per


And the result will become



Id  Emails
1 abc@gmail.com
2 NULL
3 def@gmail.com, xyz@gmail.com


This will work even your data contains invalid XML characters



the '"},{"_":"' is safe because if you data contain '"},{"_":"', it will be escaped to "},{"_":"



You can replace ', ' with any string separator





And in SQL Server 2017, Azure SQL Database



You can use the new STRING_AGG function






share|improve this answer





















  • 3





    Good use of the STUFF function to nix the leading two characters.

    – David
    Aug 11 '11 at 23:12






  • 3





    I like this solution best, because I can easily use it in a select list by appending 'as <label>'. I am not sure how to do this with the solution of @Ritesh.

    – R. Schreurs
    Aug 2 '13 at 8:27






  • 12





    This is better than the accepted answer because this option also handles un-escaping XML reserverd characters such as <, >, &, etc. which FOR XML PATH('') will automatically escape.

    – BateTech
    Apr 7 '14 at 21:35











  • This is an awesome response as it resolved the issue and provides the best ways of doing things in different versions of SQL now I wish I could use 2017/Azure

    – Chris Ward
    May 21 '18 at 14:27



















265





+150









SQL Server 2017+ and SQL Azure: STRING_AGG



Starting with the next version of SQL Server, we can finally concatenate across rows without having to resort to any variable or XML witchery.



STRING_AGG (Transact-SQL)



Without grouping



SELECT STRING_AGG(Name, ', ') AS Departments
FROM HumanResources.Department;


With grouping :



SELECT GroupName, STRING_AGG(Name, ', ') AS Departments
FROM HumanResources.Department
GROUP BY GroupName;


With grouping and sub-sorting



SELECT GroupName, STRING_AGG(Name, ', ') WITHIN GROUP (ORDER BY Name ASC) AS Departments
FROM HumanResources.Department
GROUP BY GroupName;





share|improve this answer





















  • 1





    And, unlike CLR solutions, you have control over the sorting.

    – canon
    Jul 10 '17 at 16:17






  • 2





    This works with SQL Azure. Great answer!

    – user2721607
    Oct 11 '17 at 20:27






  • 2





    This also worked for me in Azure SQL. Brilliant!

    – Kevin Stone
    Jan 4 '18 at 20:31



















111














In MySQL there is a function, GROUP_CONCAT(), which allows you to concatenate the values from multiple rows. Example:



SELECT 1 AS a, GROUP_CONCAT(name ORDER BY name ASC SEPARATOR ', ') AS people 
FROM users
WHERE id IN (1,2,3)
GROUP BY a





share|improve this answer





















  • 2





    Used to love this one, have not seen a alternative to this function with any other Db yet!

    – Binoj Antony
    Jun 18 '09 at 6:05






  • 1





    This totally solved my problem. I was trying to pull all the payment dates for a given charge on an account, this solved it perfectly. Thanks!

    – Maximus
    Aug 26 '16 at 15:47











  • works well. But when i use SEPARATOR '", "' i'll miss some chars at the end of the last entry. why can this happen?

    – gooleem
    Nov 27 '16 at 13:05











  • @gooleem I'm not clear on what you mean, but this function only puts the separator between items, not after. If that's not the answer, I'd recommend posting a new question.

    – Darryl Hein
    Dec 4 '16 at 23:41











  • @DarrylHein for my needs i used the separator as above. But this cuts me some chars at the very end of the output. This is very strange and seems to be a bug. I dont have a solution, i just workedaround.

    – gooleem
    Dec 6 '16 at 9:28





















52














Use COALESCE - Learn more from here



For an example:




102



103



104




Then write below code in sql server,



Declare @Numbers AS Nvarchar(MAX) -- It must not be MAX if you have few numbers 
SELECT @Numbers = COALESCE(@Numbers + ',', '') + Number
FROM TableName where Number IS NOT NULL

SELECT @Numbers


Output would be:



102,103,104





share|improve this answer





















  • 2





    This is really the best solution IMO as it avoids the encoding issues that FOR XML presents. I used Declare @Numbers AS Nvarchar(MAX) and it worked fine. Can you explain why you recommend not using it please?

    – EvilDr
    Aug 3 '16 at 15:01






  • 6





    This solution has already been posted 8 years ago! stackoverflow.com/a/194887/986862

    – Andre Figueiredo
    May 3 '17 at 21:53











  • Why is this query returns ??? symbols instead of Cyrillic ones? Is this just output issue?

    – Akmal Salikhov
    Dec 7 '17 at 11:31



















47














Postgres arrays are awesome. Example:



Create some test data:



postgres=# c test
You are now connected to database "test" as user "hgimenez".
test=# create table names (name text);
CREATE TABLE
test=# insert into names (name) values ('Peter'), ('Paul'), ('Mary');
INSERT 0 3
test=# select * from names;
name
-------
Peter
Paul
Mary
(3 rows)


Aggregate them in an array:



test=# select array_agg(name) from names;
array_agg
-------------------
{Peter,Paul,Mary}
(1 row)


Convert the array to a comma delimited string:



test=# select array_to_string(array_agg(name), ', ') from names;
array_to_string
-------------------
Peter, Paul, Mary
(1 row)


DONE



Since PostgreSQL 9.0 it is even easier.






share|improve this answer


























  • If you need more than one column, for example their employee id in brackets use the concat operator: select array_to_string(array_agg(name||'('||id||')'

    – Richard Fox
    Feb 27 '15 at 11:50











  • Not applicable to sql-server, only to mysql

    – GoldBishop
    May 4 '17 at 15:03



















45














Oracle 11g Release 2 supports the LISTAGG function. Documentation here.



COLUMN employees FORMAT A50

SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
FROM emp
GROUP BY deptno;

DEPTNO EMPLOYEES
---------- --------------------------------------------------
10 CLARK,KING,MILLER
20 ADAMS,FORD,JONES,SCOTT,SMITH
30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

3 rows selected.


Warning



Be careful implementing this function if there is possibility of the resulting string going over 4000 characters. It will throw an exception. If that's the case then you need to either handle the exception or roll your own function that prevents the joined string from going over 4000 characters.






share|improve this answer





















  • 1





    For older versions of Oracle, wm_concat is perfect. Its use is explained in the link gift by Alex. Thnks Alex!

    – toscanelli
    Jul 20 '15 at 13:04











  • LISTAGG works perfect! Just read the document linked here. wm_concat removed from version 12c onwards.

    – asgs
    Jun 22 '16 at 18:56





















32














In SQL Server 2005 and later, use the query below to concatenate the rows.



DECLARE @t table
(
Id int,
Name varchar(10)
)
INSERT INTO @t
SELECT 1,'a' UNION ALL
SELECT 1,'b' UNION ALL
SELECT 2,'c' UNION ALL
SELECT 2,'d'

SELECT ID,
stuff(
(
SELECT ','+ [Name] FROM @t WHERE Id = t.Id FOR XML PATH('')
),1,1,'')
FROM (SELECT DISTINCT ID FROM @t ) t





share|improve this answer





















  • 2





    I believe this fails when the values contain XML symbols such as < or &.

    – Sam
    Aug 13 '13 at 1:36



















27














I don't have access to a SQL Server at home, so I'm guess at the syntax here, but it's more or less:



DECLARE @names VARCHAR(500)

SELECT @names = @names + ' ' + Name
FROM Names





share|improve this answer



















  • 10





    You'd need to init @names to something non-null, otherwise you will get NULL throughout; you'd also need to handle the delimiter (including the unnecessary one)

    – Marc Gravell
    Oct 12 '08 at 9:10






  • 3





    the only problem with this approach (which i use all the time) is that you can't embed it

    – ekkis
    Nov 23 '12 at 22:22











  • To get rid of the leading space change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ' ' END + Name FROM Names

    – Tian van Heerden
    Mar 4 '16 at 9:15













  • Also, you have to check that Name is not null, you can do it by doing: SELECT @names = @names + ISNULL(' ' + Name, '')

    – Vita1ij
    Mar 18 '16 at 10:49



















25














A recursive CTE solution was suggested, but no code provided. The code below is an example of a recursive CTE -- note that although the results match the question, the data doesn't quite match the given description, as I assume that you really want to be doing this on groups of rows, not all rows in the table. Changing it to match all rows in the table is left as an exercise for the reader.



;with basetable as 
( SELECT id, CAST(name as varchar(max))name,
ROW_NUMBER() OVER(Partition By id order by seq) rw,
COUNT(*) OVER (Partition By id) recs
FROM (VALUES (1, 'Johnny', 1), (1,'M', 2),
(2,'Bill', 1), (2, 'S.', 4), (2, 'Preston', 5), (2, 'Esq.', 6),
(3, 'Ted', 1), (3,'Theodore', 2), (3,'Logan', 3),
(4, 'Peter', 1), (4,'Paul', 2), (4,'Mary', 3)

)g(id, name, seq)
),
rCTE as (
SELECT recs, id, name, rw from basetable where rw=1
UNION ALL
SELECT b.recs, r.ID, r.name +', '+ b.name name, r.rw+1
FROM basetable b
inner join rCTE r
on b.id = r.id and b.rw = r.rw+1
)
SELECT name FROM rCTE
WHERE recs = rw and ID=4





share|improve this answer
























  • For the flabbergasted: this query inserts 12 rows (a 3 columns) into a temporary basetable, then creates a recursive Common Table Expression (rCTE) and then flattens the name column into a comma-separated string for 4 groups of ids. At first glance, I think this is more work than what most other solutions for SQL Server do.

    – knb
    Jul 24 '17 at 13:34








  • 1





    @knb: not sure if that is praise,condemnation,or just surprise. The base table is because I like my examples to actually work, it doesn't really have anything to do with the question.

    – jmoreno
    Jul 25 '17 at 2:20



















23














Starting with PostgreSQL 9.0 this is quite simple:



select string_agg(name, ',') 
from names;


In versions before 9.0 array_agg() can be used as shown by hgmnz






share|improve this answer


























  • To do this with columns that are not of type text, you need to add a type cast: SELECT string_agg(non_text_type::text, ',') FROM table

    – Torben Kohlmeier
    May 17 '13 at 12:05













  • @TorbenKohlmeier: you only need that for non-character columns (e.g. integer, decimal). It works just fine for varchar or char

    – a_horse_with_no_name
    May 17 '13 at 12:11



















23














You need to create a variable that will hold your final result and select into it, like so.



Easiest Solution



DECLARE @char VARCHAR(MAX);

SELECT @char = COALESCE(@char + ', ' + [column], [column])
FROM [table];

PRINT @char;





share|improve this answer































    21














    In SQL Server vNext this will be built in with the STRING_AGG function, read more about it here:
    https://msdn.microsoft.com/en-us/library/mt790580.aspx






    share|improve this answer

































      17














      Using XML helped me in getting rows separated with commas. For the extra comma we can use the replace function of SQL Server. Instead of adding a comma, use of the AS 'data()' will concatenate the rows with spaces, which later can be replaced with commas as the syntax written below.



      REPLACE(
      (select FName AS 'data()' from NameList for xml path(''))
      , ' ', ', ')





      share|improve this answer





















      • 2





        This is the best answer here in my opinon. The use of declare variable is no good when you need to join in another table, and this is nice and short. Good work.

        – David Roussel
        Jun 2 '11 at 16:22






      • 7





        that's not working good if FName data has spaces already, for example "My Name"

        – binball
        Jun 8 '11 at 15:16













      • Really it is working for me on ms-sql 2016 Select REPLACE( (select Name AS 'data()' from Brand Where Id IN (1,2,3,4) for xml path('')) , ' ', ', ') as allBrands

        – Rejwanul Reja
        Apr 28 '17 at 10:13



















      17














      A ready-to-use solution, with no extra commas:



      select substring(
      (select ', '+Name AS 'data()' from Names for xml path(''))
      ,3, 255) as "MyList"


      An empty list will result in NULL value.
      Usually you will insert the list into a table column or program variable: adjust the 255 max length to your need.



      (Diwakar and Jens Frandsen provided good answers, but need improvement.)






      share|improve this answer


























      • There is a space before the comma when using this :(

        – slayernoah
        Nov 18 '15 at 18:23








      • 1





        Just replace ', ' with ',' if you don't want the extra space.

        – Daniel Reis
        Nov 18 '15 at 23:17



















      11














      SELECT STUFF((SELECT ', ' + name FROM [table] FOR XML PATH('')), 1, 2, '')


      Here's a sample:



      DECLARE @t TABLE (name VARCHAR(10))
      INSERT INTO @t VALUES ('Peter'), ('Paul'), ('Mary')
      SELECT STUFF((SELECT ', ' + name FROM @t FOR XML PATH('')), 1, 2, '')
      --Peter, Paul, Mary





      share|improve this answer


























      • Thanks so much for giving the smallest possible solution, along with a working example! I had no idea why the top-voted answer works, nor how to replicate it.

        – jpaugh
        Mar 19 '18 at 14:21





















      10














      DECLARE @Names VARCHAR(8000)
      SELECT @name = ''
      SELECT @Names = @Names + ',' + Names FROM People
      SELECT SUBSTRING(2, @Names, 7998)


      This puts the stray comma at the beginning.



      However, if you need other columns, or to CSV a child table you need to wrap this in a scalar user defined field (UDF).



      You can use XML path as a correlated subquery in the SELECT clause too (but I'd have to wait until I go back to work because Google doesn't do work stuff at home :-)






      share|improve this answer

































        9














        With the other answers, the person reading the answer must be aware of a specific domain table such as vehicle or student. The table must be created and populated with data to test a solution.



        Below is an example that uses SQL Server "Information_Schema.Columns" table. By using this solution, no tables need to be created or data added. This example creates a comma separated list of column names for all tables in the database.



        SELECT
        Table_Name
        ,STUFF((
        SELECT ',' + Column_Name
        FROM INFORMATION_SCHEMA.Columns Columns
        WHERE Tables.Table_Name = Columns.Table_Name
        ORDER BY Column_Name
        FOR XML PATH ('')), 1, 1, ''
        )Columns
        FROM INFORMATION_SCHEMA.Columns Tables
        GROUP BY TABLE_NAME





        share|improve this answer































          7














          For Oracle DBs, see this question: How can multiple rows be concatenated into one in Oracle without creating a stored procedure?



          The best answer appears to be by @Emmanuel, using the built-in LISTAGG() function, available in Oracle 11g Release 2 and later.



          SELECT question_id,
          LISTAGG(element_id, ',') WITHIN GROUP (ORDER BY element_id)
          FROM YOUR_TABLE;
          GROUP BY question_id


          as @user762952 pointed out, and according to Oracle's documentation http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php, the WM_CONCAT() function is also an option. It seems stable, but Oracle explicitly recommends against using it for any application SQL, so use at your own risk.



          Other than that, you will have to write your own function; the Oracle document above has a guide on how to do that.






          share|improve this answer

































            7














            I really liked elegancy of Dana's answer. Just wanted to make it complete.



            DECLARE @names VARCHAR(MAX)
            SET @names = ''

            SELECT @names = @names + ', ' + Name FROM Names

            -- Deleting last two symbols (', ')
            SET @sSql = LEFT(@sSql, LEN(@sSql) - 1)





            share|improve this answer


























            • If you are deleting the last two symbols ', ', then you need to add ', ' after Name ('SELECT @names = @names + Name + ', ' FROM Names'). That way the last two chars will always be ', '.

              – Justin T
              Dec 18 '15 at 11:04













            • In my case I needed to get rid of the leading comma so change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ', ' END + Name FROM Names then you don't have to truncate it afterwards.

              – Tian van Heerden
              Mar 4 '16 at 9:13



















            6














            To avoid null values you can use CONCAT()



            DECLARE @names VARCHAR(500)
            SELECT @names = CONCAT(@names, ' ', name)
            FROM Names
            select @names





            share|improve this answer
























            • It would be nice to know why CONCAT works. A link to MSDN would be nice.

              – DaveBoltman
              Sep 20 '16 at 8:15



















            6














            This answer will require some privilege in server to work.



            Assemblies are a good option for you. There are a lot of sites that explain how to create it. The one I think is very well explained is this one



            If you want, I have already created the assembly, and it is possible to download the DLL here.



            Once you have downloaded it, you will need to run the following script in your SQL Server:



            CREATE Assembly concat_assembly 
            AUTHORIZATION dbo
            FROM '<PATH TO Concat.dll IN SERVER>'
            WITH PERMISSION_SET = SAFE;
            GO

            CREATE AGGREGATE dbo.concat (

            @Value NVARCHAR(MAX)
            , @Delimiter NVARCHAR(4000)

            ) RETURNS NVARCHAR(MAX)
            EXTERNAL Name concat_assembly.[Concat.Concat];
            GO

            sp_configure 'clr enabled', 1;
            RECONFIGURE


            Observe that the path to assembly may be accessible to server. Since you have successfully done all the steps, you can use the function like:



            SELECT dbo.Concat(field1, ',')
            FROM Table1


            Hope it helps!!!






            share|improve this answer































              5














              I usually use select like this to concatenate strings in SQL Server:



              with lines as 
              (
              select
              row_number() over(order by id) id, -- id is a line id
              line -- line of text.
              from
              source -- line source
              ),
              result_lines as
              (
              select
              id,
              cast(line as nvarchar(max)) line
              from
              lines
              where
              id = 1
              union all
              select
              l.id,
              cast(r.line + N', ' + l.line as nvarchar(max))
              from
              lines l
              inner join
              result_lines r
              on
              l.id = r.id + 1
              )
              select top 1
              line
              from
              result_lines
              order by
              id desc





              share|improve this answer

































                5














                If you want to deal with nulls you can do it by adding a where clause or add another COALESCE around the first one.



                DECLARE @Names VARCHAR(8000) 
                SELECT @Names = COALESCE(COALESCE(@Names + ', ', '') + Name, @Names) FROM People





                share|improve this answer































                  5














                  MySQL complete Example:



                  We have Users which can have many Data's and we want to have an output, where we can see all users Datas in a list:



                  Result:



                  ___________________________
                  | id | rowList |
                  |-------------------------|
                  | 0 | 6, 9 |
                  | 1 | 1,2,3,4,5,7,8,1 |
                  |_________________________|


                  Table Setup:



                  CREATE TABLE `Data` (
                  `id` int(11) NOT NULL,
                  `user_id` int(11) NOT NULL
                  ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;


                  INSERT INTO `Data` (`id`, `user_id`) VALUES
                  (1, 1),
                  (2, 1),
                  (3, 1),
                  (4, 1),
                  (5, 1),
                  (6, 0),
                  (7, 1),
                  (8, 1),
                  (9, 0),
                  (10, 1);


                  CREATE TABLE `User` (
                  `id` int(11) NOT NULL
                  ) ENGINE=InnoDB DEFAULT CHARSET=latin1;


                  INSERT INTO `User` (`id`) VALUES
                  (0),
                  (1);


                  Query:



                  SELECT User.id, GROUP_CONCAT(Data.id ORDER BY Data.id) AS rowList FROM User LEFT JOIN Data ON User.id = Data.user_id GROUP BY User.id





                  share|improve this answer































                    4














                    In Oracle, it is wm_concat. I believe this function is available in the 10g release and higher.






                    share|improve this answer

































                      4














                      This can be useful too



                      create table #test (id int,name varchar(10))
                      --use separate inserts on older versions of SQL Server
                      insert into #test values (1,'Peter'), (1,'Paul'), (1,'Mary'), (2,'Alex'), (3,'Jack')

                      DECLARE @t VARCHAR(255)
                      SELECT @t = ISNULL(@t + ',' + name, name) FROM #test WHERE id = 1
                      select @t
                      drop table #test


                      returns



                      Peter,Paul,Mary





                      share|improve this answer



















                      • 5





                        Unfortunately this behavior seems not to be officially supported. MSDN says: "If a variable is referenced in a select list, it should be assigned a scalar value or the SELECT statement should only return one row." And there are people who observed problems: sqlmag.com/sql-server/multi-row-variable-assignment-and-order

                        – blueling
                        Dec 5 '13 at 9:11





















                      3














                      This method applies to Teradata Aster database only as it utilizes its NPATH function.



                      Again, we have table Students



                      SubjectID       StudentName
                      ---------- -------------
                      1 Mary
                      1 John
                      1 Sam
                      2 Alaina
                      2 Edward


                      Then with NPATH it is just single SELECT:



                      SELECT * FROM npath(
                      ON Students
                      PARTITION BY SubjectID
                      ORDER BY StudentName
                      MODE(nonoverlapping)
                      PATTERN('A*')
                      SYMBOLS(
                      'true' as A
                      )
                      RESULT(
                      FIRST(SubjectID of A) as SubjectID,
                      ACCUMULATE(StudentName of A) as StudentName
                      )
                      );


                      Result:



                      SubjectID       StudentName
                      ---------- -------------
                      1 [John, Mary, Sam]
                      2 [Alaina, Edward]





                      share|improve this answer



























                        1 2
                        next


                        protected by Community Aug 2 '11 at 14:32



                        Thank you for your interest in this question.
                        Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                        Would you like to answer one of these unanswered questions instead?














                        44 Answers
                        44






                        active

                        oldest

                        votes








                        44 Answers
                        44






                        active

                        oldest

                        votes









                        active

                        oldest

                        votes






                        active

                        oldest

                        votes








                        1 2
                        next










                        1232














                        If you are on SQL Server 2017 or Azure, see Mathieu Renda answer.



                        I had a similar issue when I was trying to join two tables with one-to-many relationships. In SQL 2005 I found that XML PATH method can handle the concatenation of the rows very easily.



                        If there is a table called STUDENTS



                        SubjectID       StudentName
                        ---------- -------------
                        1 Mary
                        1 John
                        1 Sam
                        2 Alaina
                        2 Edward


                        Result I expected was:



                        SubjectID       StudentName
                        ---------- -------------
                        1 Mary, John, Sam
                        2 Alaina, Edward


                        I used the following T-SQL:



                        SELECT Main.SubjectID,
                        LEFT(Main.Students,Len(Main.Students)-1) As "Students"
                        FROM
                        (
                        SELECT DISTINCT ST2.SubjectID,
                        (
                        SELECT ST1.StudentName + ',' AS [text()]
                        FROM dbo.Students ST1
                        WHERE ST1.SubjectID = ST2.SubjectID
                        ORDER BY ST1.SubjectID
                        FOR XML PATH ('')
                        ) [Students]
                        FROM dbo.Students ST2
                        ) [Main]


                        You can do the same thing in a more compact way if you can concat the commas at the beginning and use substring to skip the first one so you don't need to do a sub-query:



                        SELECT DISTINCT ST2.SubjectID, 
                        SUBSTRING(
                        (
                        SELECT ','+ST1.StudentName AS [text()]
                        FROM dbo.Students ST1
                        WHERE ST1.SubjectID = ST2.SubjectID
                        ORDER BY ST1.SubjectID
                        FOR XML PATH ('')
                        ), 2, 1000) [Students]
                        FROM dbo.Students ST2





                        share|improve this answer





















                        • 10





                          Great solution. The following may be helpful if you need to handle special characters like those in HTML: Rob Farley: Handling special characters with FOR XML PATH('').

                          – user140628
                          Apr 17 '13 at 12:35






                        • 8





                          Apparently this doesn't work if the names contain XML characters such as < or &. See @BenHinman's comment.

                          – Sam
                          Aug 13 '13 at 1:26






                        • 21





                          NB: This method is reliant on undocumented behavior of FOR XML PATH (''). That means it should not be considered reliable as any patch or update could alter how this functions. It's basically relying on a deprecated feature.

                          – Bacon Bits
                          Nov 13 '14 at 18:54






                        • 23





                          @Whelkaholism The bottom line is that FOR XML is intended to generate XML, not concatenate arbitrary strings. That's why it escapes &, < and > to XML entity codes (&amp;, &lt;, &gt;). I assume it also will escape " and ' to &quot; and &apos; in attributes as well. It's not GROUP_CONCAT(), string_agg(), array_agg(), listagg(), etc. even if you can kind of make it do that. We should be spending our time demanding Microsoft implement a proper function.

                          – Bacon Bits
                          Mar 23 '15 at 14:15








                        • 9





                          Good news: MS SQL Server will be adding string_agg in v.Next. and all of this can go away.

                          – Jason C
                          Apr 6 '17 at 0:32


















                        1232














                        If you are on SQL Server 2017 or Azure, see Mathieu Renda answer.



                        I had a similar issue when I was trying to join two tables with one-to-many relationships. In SQL 2005 I found that XML PATH method can handle the concatenation of the rows very easily.



                        If there is a table called STUDENTS



                        SubjectID       StudentName
                        ---------- -------------
                        1 Mary
                        1 John
                        1 Sam
                        2 Alaina
                        2 Edward


                        Result I expected was:



                        SubjectID       StudentName
                        ---------- -------------
                        1 Mary, John, Sam
                        2 Alaina, Edward


                        I used the following T-SQL:



                        SELECT Main.SubjectID,
                        LEFT(Main.Students,Len(Main.Students)-1) As "Students"
                        FROM
                        (
                        SELECT DISTINCT ST2.SubjectID,
                        (
                        SELECT ST1.StudentName + ',' AS [text()]
                        FROM dbo.Students ST1
                        WHERE ST1.SubjectID = ST2.SubjectID
                        ORDER BY ST1.SubjectID
                        FOR XML PATH ('')
                        ) [Students]
                        FROM dbo.Students ST2
                        ) [Main]


                        You can do the same thing in a more compact way if you can concat the commas at the beginning and use substring to skip the first one so you don't need to do a sub-query:



                        SELECT DISTINCT ST2.SubjectID, 
                        SUBSTRING(
                        (
                        SELECT ','+ST1.StudentName AS [text()]
                        FROM dbo.Students ST1
                        WHERE ST1.SubjectID = ST2.SubjectID
                        ORDER BY ST1.SubjectID
                        FOR XML PATH ('')
                        ), 2, 1000) [Students]
                        FROM dbo.Students ST2





                        share|improve this answer





















                        • 10





                          Great solution. The following may be helpful if you need to handle special characters like those in HTML: Rob Farley: Handling special characters with FOR XML PATH('').

                          – user140628
                          Apr 17 '13 at 12:35






                        • 8





                          Apparently this doesn't work if the names contain XML characters such as < or &. See @BenHinman's comment.

                          – Sam
                          Aug 13 '13 at 1:26






                        • 21





                          NB: This method is reliant on undocumented behavior of FOR XML PATH (''). That means it should not be considered reliable as any patch or update could alter how this functions. It's basically relying on a deprecated feature.

                          – Bacon Bits
                          Nov 13 '14 at 18:54






                        • 23





                          @Whelkaholism The bottom line is that FOR XML is intended to generate XML, not concatenate arbitrary strings. That's why it escapes &, < and > to XML entity codes (&amp;, &lt;, &gt;). I assume it also will escape " and ' to &quot; and &apos; in attributes as well. It's not GROUP_CONCAT(), string_agg(), array_agg(), listagg(), etc. even if you can kind of make it do that. We should be spending our time demanding Microsoft implement a proper function.

                          – Bacon Bits
                          Mar 23 '15 at 14:15








                        • 9





                          Good news: MS SQL Server will be adding string_agg in v.Next. and all of this can go away.

                          – Jason C
                          Apr 6 '17 at 0:32
















                        1232












                        1232








                        1232







                        If you are on SQL Server 2017 or Azure, see Mathieu Renda answer.



                        I had a similar issue when I was trying to join two tables with one-to-many relationships. In SQL 2005 I found that XML PATH method can handle the concatenation of the rows very easily.



                        If there is a table called STUDENTS



                        SubjectID       StudentName
                        ---------- -------------
                        1 Mary
                        1 John
                        1 Sam
                        2 Alaina
                        2 Edward


                        Result I expected was:



                        SubjectID       StudentName
                        ---------- -------------
                        1 Mary, John, Sam
                        2 Alaina, Edward


                        I used the following T-SQL:



                        SELECT Main.SubjectID,
                        LEFT(Main.Students,Len(Main.Students)-1) As "Students"
                        FROM
                        (
                        SELECT DISTINCT ST2.SubjectID,
                        (
                        SELECT ST1.StudentName + ',' AS [text()]
                        FROM dbo.Students ST1
                        WHERE ST1.SubjectID = ST2.SubjectID
                        ORDER BY ST1.SubjectID
                        FOR XML PATH ('')
                        ) [Students]
                        FROM dbo.Students ST2
                        ) [Main]


                        You can do the same thing in a more compact way if you can concat the commas at the beginning and use substring to skip the first one so you don't need to do a sub-query:



                        SELECT DISTINCT ST2.SubjectID, 
                        SUBSTRING(
                        (
                        SELECT ','+ST1.StudentName AS [text()]
                        FROM dbo.Students ST1
                        WHERE ST1.SubjectID = ST2.SubjectID
                        ORDER BY ST1.SubjectID
                        FOR XML PATH ('')
                        ), 2, 1000) [Students]
                        FROM dbo.Students ST2





                        share|improve this answer















                        If you are on SQL Server 2017 or Azure, see Mathieu Renda answer.



                        I had a similar issue when I was trying to join two tables with one-to-many relationships. In SQL 2005 I found that XML PATH method can handle the concatenation of the rows very easily.



                        If there is a table called STUDENTS



                        SubjectID       StudentName
                        ---------- -------------
                        1 Mary
                        1 John
                        1 Sam
                        2 Alaina
                        2 Edward


                        Result I expected was:



                        SubjectID       StudentName
                        ---------- -------------
                        1 Mary, John, Sam
                        2 Alaina, Edward


                        I used the following T-SQL:



                        SELECT Main.SubjectID,
                        LEFT(Main.Students,Len(Main.Students)-1) As "Students"
                        FROM
                        (
                        SELECT DISTINCT ST2.SubjectID,
                        (
                        SELECT ST1.StudentName + ',' AS [text()]
                        FROM dbo.Students ST1
                        WHERE ST1.SubjectID = ST2.SubjectID
                        ORDER BY ST1.SubjectID
                        FOR XML PATH ('')
                        ) [Students]
                        FROM dbo.Students ST2
                        ) [Main]


                        You can do the same thing in a more compact way if you can concat the commas at the beginning and use substring to skip the first one so you don't need to do a sub-query:



                        SELECT DISTINCT ST2.SubjectID, 
                        SUBSTRING(
                        (
                        SELECT ','+ST1.StudentName AS [text()]
                        FROM dbo.Students ST1
                        WHERE ST1.SubjectID = ST2.SubjectID
                        ORDER BY ST1.SubjectID
                        FOR XML PATH ('')
                        ), 2, 1000) [Students]
                        FROM dbo.Students ST2






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Aug 2 '18 at 11:20









                        StefanJCollier

                        1,0201020




                        1,0201020










                        answered Feb 13 '09 at 11:53







                        Ritesh















                        • 10





                          Great solution. The following may be helpful if you need to handle special characters like those in HTML: Rob Farley: Handling special characters with FOR XML PATH('').

                          – user140628
                          Apr 17 '13 at 12:35






                        • 8





                          Apparently this doesn't work if the names contain XML characters such as < or &. See @BenHinman's comment.

                          – Sam
                          Aug 13 '13 at 1:26






                        • 21





                          NB: This method is reliant on undocumented behavior of FOR XML PATH (''). That means it should not be considered reliable as any patch or update could alter how this functions. It's basically relying on a deprecated feature.

                          – Bacon Bits
                          Nov 13 '14 at 18:54






                        • 23





                          @Whelkaholism The bottom line is that FOR XML is intended to generate XML, not concatenate arbitrary strings. That's why it escapes &, < and > to XML entity codes (&amp;, &lt;, &gt;). I assume it also will escape " and ' to &quot; and &apos; in attributes as well. It's not GROUP_CONCAT(), string_agg(), array_agg(), listagg(), etc. even if you can kind of make it do that. We should be spending our time demanding Microsoft implement a proper function.

                          – Bacon Bits
                          Mar 23 '15 at 14:15








                        • 9





                          Good news: MS SQL Server will be adding string_agg in v.Next. and all of this can go away.

                          – Jason C
                          Apr 6 '17 at 0:32
















                        • 10





                          Great solution. The following may be helpful if you need to handle special characters like those in HTML: Rob Farley: Handling special characters with FOR XML PATH('').

                          – user140628
                          Apr 17 '13 at 12:35






                        • 8





                          Apparently this doesn't work if the names contain XML characters such as < or &. See @BenHinman's comment.

                          – Sam
                          Aug 13 '13 at 1:26






                        • 21





                          NB: This method is reliant on undocumented behavior of FOR XML PATH (''). That means it should not be considered reliable as any patch or update could alter how this functions. It's basically relying on a deprecated feature.

                          – Bacon Bits
                          Nov 13 '14 at 18:54






                        • 23





                          @Whelkaholism The bottom line is that FOR XML is intended to generate XML, not concatenate arbitrary strings. That's why it escapes &, < and > to XML entity codes (&amp;, &lt;, &gt;). I assume it also will escape " and ' to &quot; and &apos; in attributes as well. It's not GROUP_CONCAT(), string_agg(), array_agg(), listagg(), etc. even if you can kind of make it do that. We should be spending our time demanding Microsoft implement a proper function.

                          – Bacon Bits
                          Mar 23 '15 at 14:15








                        • 9





                          Good news: MS SQL Server will be adding string_agg in v.Next. and all of this can go away.

                          – Jason C
                          Apr 6 '17 at 0:32










                        10




                        10





                        Great solution. The following may be helpful if you need to handle special characters like those in HTML: Rob Farley: Handling special characters with FOR XML PATH('').

                        – user140628
                        Apr 17 '13 at 12:35





                        Great solution. The following may be helpful if you need to handle special characters like those in HTML: Rob Farley: Handling special characters with FOR XML PATH('').

                        – user140628
                        Apr 17 '13 at 12:35




                        8




                        8





                        Apparently this doesn't work if the names contain XML characters such as < or &. See @BenHinman's comment.

                        – Sam
                        Aug 13 '13 at 1:26





                        Apparently this doesn't work if the names contain XML characters such as < or &. See @BenHinman's comment.

                        – Sam
                        Aug 13 '13 at 1:26




                        21




                        21





                        NB: This method is reliant on undocumented behavior of FOR XML PATH (''). That means it should not be considered reliable as any patch or update could alter how this functions. It's basically relying on a deprecated feature.

                        – Bacon Bits
                        Nov 13 '14 at 18:54





                        NB: This method is reliant on undocumented behavior of FOR XML PATH (''). That means it should not be considered reliable as any patch or update could alter how this functions. It's basically relying on a deprecated feature.

                        – Bacon Bits
                        Nov 13 '14 at 18:54




                        23




                        23





                        @Whelkaholism The bottom line is that FOR XML is intended to generate XML, not concatenate arbitrary strings. That's why it escapes &, < and > to XML entity codes (&amp;, &lt;, &gt;). I assume it also will escape " and ' to &quot; and &apos; in attributes as well. It's not GROUP_CONCAT(), string_agg(), array_agg(), listagg(), etc. even if you can kind of make it do that. We should be spending our time demanding Microsoft implement a proper function.

                        – Bacon Bits
                        Mar 23 '15 at 14:15







                        @Whelkaholism The bottom line is that FOR XML is intended to generate XML, not concatenate arbitrary strings. That's why it escapes &, < and > to XML entity codes (&amp;, &lt;, &gt;). I assume it also will escape " and ' to &quot; and &apos; in attributes as well. It's not GROUP_CONCAT(), string_agg(), array_agg(), listagg(), etc. even if you can kind of make it do that. We should be spending our time demanding Microsoft implement a proper function.

                        – Bacon Bits
                        Mar 23 '15 at 14:15






                        9




                        9





                        Good news: MS SQL Server will be adding string_agg in v.Next. and all of this can go away.

                        – Jason C
                        Apr 6 '17 at 0:32







                        Good news: MS SQL Server will be adding string_agg in v.Next. and all of this can go away.

                        – Jason C
                        Apr 6 '17 at 0:32















                        942















                        This answer may return unexpected results when an ORDER BY clause is present. For consistent results, use one of the FOR XML PATH methods detailed in other answers.




                        Use COALESCE:



                        DECLARE @Names VARCHAR(8000) 
                        SELECT @Names = COALESCE(@Names + ', ', '') + Name
                        FROM People


                        Just some explanation (since this answer seems to get relatively regular views):




                        • Coalesce is really just a helpful cheat that accomplishes two things:


                        1) No need to initialize @Names with an empty string value.



                        2) No need to strip off an extra separator at the end.




                        • The solution above will give incorrect results if a row has a NULL Name value (if there is a NULL, the NULL will make @Names NULL after that row, and the next row will start over as an empty string again. Easily fixed with one of two solutions:


                        DECLARE @Names VARCHAR(8000) 
                        SELECT @Names = COALESCE(@Names + ', ', '') + Name
                        FROM People
                        WHERE Name IS NOT NULL


                        or:



                        DECLARE @Names VARCHAR(8000) 
                        SELECT @Names = COALESCE(@Names + ', ', '') +
                        ISNULL(Name, 'N/A')
                        FROM People


                        Depending on what behavior you want (the first option just filters NULLs out, the second option keeps them in the list with a marker message [replace 'N/A' with whatever is appropriate for you]).






                        share|improve this answer





















                        • 67





                          To be clear, coalesce has nothing to do with creating the list, it just makes sure that NULL values are not included.

                          – Graeme Perrow
                          Feb 13 '09 at 12:02






                        • 16





                          @Graeme Perrow It doesn't exclude NULL values (a WHERE is required for that -- this will lose results if one of the input values is NULL), and it is required in this approach because: NULL + non-NULL -> NULL and non-NULL + NULL -> NULL; also @Name is NULL by default and, in fact, that property is used as an implicit sentinel here to determine if a ', ' should be added or not.

                          – user166390
                          Aug 15 '10 at 18:57








                        • 58





                          Please note that this method of concatenation relies on SQL Server executing the query with a particular plan. I have been caught out using this method (with the addition of an ORDER BY). When it was dealing with a small number of rows it worked fine but with more data SQL Server chose a different plan which resulted in selecting the first item with no concatenation whatsoever. See this article by Anith Sen.

                          – fbarber
                          Apr 26 '12 at 2:18






                        • 14





                          This method cannot be used as a sub query in a select list or where-clause, because it use a tSQL variable. In such cases you could use the methods offered by @Ritesh

                          – R. Schreurs
                          Aug 2 '13 at 8:10






                        • 10





                          This is not a reliable method of concatenation. It is unsupported and should not be used (per Microsoft, e.g. support.microsoft.com/en-us/kb/287515, connect.microsoft.com/SQLServer/Feedback/Details/704389). It can change without warning. Use the XML PATH technique discussed in stackoverflow.com/questions/5031204/… I wrote more here: marc.durdin.net/2015/07/…

                          – Marc Durdin
                          Jul 15 '15 at 0:23


















                        942















                        This answer may return unexpected results when an ORDER BY clause is present. For consistent results, use one of the FOR XML PATH methods detailed in other answers.




                        Use COALESCE:



                        DECLARE @Names VARCHAR(8000) 
                        SELECT @Names = COALESCE(@Names + ', ', '') + Name
                        FROM People


                        Just some explanation (since this answer seems to get relatively regular views):




                        • Coalesce is really just a helpful cheat that accomplishes two things:


                        1) No need to initialize @Names with an empty string value.



                        2) No need to strip off an extra separator at the end.




                        • The solution above will give incorrect results if a row has a NULL Name value (if there is a NULL, the NULL will make @Names NULL after that row, and the next row will start over as an empty string again. Easily fixed with one of two solutions:


                        DECLARE @Names VARCHAR(8000) 
                        SELECT @Names = COALESCE(@Names + ', ', '') + Name
                        FROM People
                        WHERE Name IS NOT NULL


                        or:



                        DECLARE @Names VARCHAR(8000) 
                        SELECT @Names = COALESCE(@Names + ', ', '') +
                        ISNULL(Name, 'N/A')
                        FROM People


                        Depending on what behavior you want (the first option just filters NULLs out, the second option keeps them in the list with a marker message [replace 'N/A' with whatever is appropriate for you]).






                        share|improve this answer





















                        • 67





                          To be clear, coalesce has nothing to do with creating the list, it just makes sure that NULL values are not included.

                          – Graeme Perrow
                          Feb 13 '09 at 12:02






                        • 16





                          @Graeme Perrow It doesn't exclude NULL values (a WHERE is required for that -- this will lose results if one of the input values is NULL), and it is required in this approach because: NULL + non-NULL -> NULL and non-NULL + NULL -> NULL; also @Name is NULL by default and, in fact, that property is used as an implicit sentinel here to determine if a ', ' should be added or not.

                          – user166390
                          Aug 15 '10 at 18:57








                        • 58





                          Please note that this method of concatenation relies on SQL Server executing the query with a particular plan. I have been caught out using this method (with the addition of an ORDER BY). When it was dealing with a small number of rows it worked fine but with more data SQL Server chose a different plan which resulted in selecting the first item with no concatenation whatsoever. See this article by Anith Sen.

                          – fbarber
                          Apr 26 '12 at 2:18






                        • 14





                          This method cannot be used as a sub query in a select list or where-clause, because it use a tSQL variable. In such cases you could use the methods offered by @Ritesh

                          – R. Schreurs
                          Aug 2 '13 at 8:10






                        • 10





                          This is not a reliable method of concatenation. It is unsupported and should not be used (per Microsoft, e.g. support.microsoft.com/en-us/kb/287515, connect.microsoft.com/SQLServer/Feedback/Details/704389). It can change without warning. Use the XML PATH technique discussed in stackoverflow.com/questions/5031204/… I wrote more here: marc.durdin.net/2015/07/…

                          – Marc Durdin
                          Jul 15 '15 at 0:23
















                        942












                        942








                        942








                        This answer may return unexpected results when an ORDER BY clause is present. For consistent results, use one of the FOR XML PATH methods detailed in other answers.




                        Use COALESCE:



                        DECLARE @Names VARCHAR(8000) 
                        SELECT @Names = COALESCE(@Names + ', ', '') + Name
                        FROM People


                        Just some explanation (since this answer seems to get relatively regular views):




                        • Coalesce is really just a helpful cheat that accomplishes two things:


                        1) No need to initialize @Names with an empty string value.



                        2) No need to strip off an extra separator at the end.




                        • The solution above will give incorrect results if a row has a NULL Name value (if there is a NULL, the NULL will make @Names NULL after that row, and the next row will start over as an empty string again. Easily fixed with one of two solutions:


                        DECLARE @Names VARCHAR(8000) 
                        SELECT @Names = COALESCE(@Names + ', ', '') + Name
                        FROM People
                        WHERE Name IS NOT NULL


                        or:



                        DECLARE @Names VARCHAR(8000) 
                        SELECT @Names = COALESCE(@Names + ', ', '') +
                        ISNULL(Name, 'N/A')
                        FROM People


                        Depending on what behavior you want (the first option just filters NULLs out, the second option keeps them in the list with a marker message [replace 'N/A' with whatever is appropriate for you]).






                        share|improve this answer
















                        This answer may return unexpected results when an ORDER BY clause is present. For consistent results, use one of the FOR XML PATH methods detailed in other answers.




                        Use COALESCE:



                        DECLARE @Names VARCHAR(8000) 
                        SELECT @Names = COALESCE(@Names + ', ', '') + Name
                        FROM People


                        Just some explanation (since this answer seems to get relatively regular views):




                        • Coalesce is really just a helpful cheat that accomplishes two things:


                        1) No need to initialize @Names with an empty string value.



                        2) No need to strip off an extra separator at the end.




                        • The solution above will give incorrect results if a row has a NULL Name value (if there is a NULL, the NULL will make @Names NULL after that row, and the next row will start over as an empty string again. Easily fixed with one of two solutions:


                        DECLARE @Names VARCHAR(8000) 
                        SELECT @Names = COALESCE(@Names + ', ', '') + Name
                        FROM People
                        WHERE Name IS NOT NULL


                        or:



                        DECLARE @Names VARCHAR(8000) 
                        SELECT @Names = COALESCE(@Names + ', ', '') +
                        ISNULL(Name, 'N/A')
                        FROM People


                        Depending on what behavior you want (the first option just filters NULLs out, the second option keeps them in the list with a marker message [replace 'N/A' with whatever is appropriate for you]).







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Apr 30 '18 at 9:26









                        Ian Kemp

                        17.5k1271102




                        17.5k1271102










                        answered Oct 12 '08 at 0:18









                        Chris ShafferChris Shaffer

                        28.5k44160




                        28.5k44160








                        • 67





                          To be clear, coalesce has nothing to do with creating the list, it just makes sure that NULL values are not included.

                          – Graeme Perrow
                          Feb 13 '09 at 12:02






                        • 16





                          @Graeme Perrow It doesn't exclude NULL values (a WHERE is required for that -- this will lose results if one of the input values is NULL), and it is required in this approach because: NULL + non-NULL -> NULL and non-NULL + NULL -> NULL; also @Name is NULL by default and, in fact, that property is used as an implicit sentinel here to determine if a ', ' should be added or not.

                          – user166390
                          Aug 15 '10 at 18:57








                        • 58





                          Please note that this method of concatenation relies on SQL Server executing the query with a particular plan. I have been caught out using this method (with the addition of an ORDER BY). When it was dealing with a small number of rows it worked fine but with more data SQL Server chose a different plan which resulted in selecting the first item with no concatenation whatsoever. See this article by Anith Sen.

                          – fbarber
                          Apr 26 '12 at 2:18






                        • 14





                          This method cannot be used as a sub query in a select list or where-clause, because it use a tSQL variable. In such cases you could use the methods offered by @Ritesh

                          – R. Schreurs
                          Aug 2 '13 at 8:10






                        • 10





                          This is not a reliable method of concatenation. It is unsupported and should not be used (per Microsoft, e.g. support.microsoft.com/en-us/kb/287515, connect.microsoft.com/SQLServer/Feedback/Details/704389). It can change without warning. Use the XML PATH technique discussed in stackoverflow.com/questions/5031204/… I wrote more here: marc.durdin.net/2015/07/…

                          – Marc Durdin
                          Jul 15 '15 at 0:23
















                        • 67





                          To be clear, coalesce has nothing to do with creating the list, it just makes sure that NULL values are not included.

                          – Graeme Perrow
                          Feb 13 '09 at 12:02






                        • 16





                          @Graeme Perrow It doesn't exclude NULL values (a WHERE is required for that -- this will lose results if one of the input values is NULL), and it is required in this approach because: NULL + non-NULL -> NULL and non-NULL + NULL -> NULL; also @Name is NULL by default and, in fact, that property is used as an implicit sentinel here to determine if a ', ' should be added or not.

                          – user166390
                          Aug 15 '10 at 18:57








                        • 58





                          Please note that this method of concatenation relies on SQL Server executing the query with a particular plan. I have been caught out using this method (with the addition of an ORDER BY). When it was dealing with a small number of rows it worked fine but with more data SQL Server chose a different plan which resulted in selecting the first item with no concatenation whatsoever. See this article by Anith Sen.

                          – fbarber
                          Apr 26 '12 at 2:18






                        • 14





                          This method cannot be used as a sub query in a select list or where-clause, because it use a tSQL variable. In such cases you could use the methods offered by @Ritesh

                          – R. Schreurs
                          Aug 2 '13 at 8:10






                        • 10





                          This is not a reliable method of concatenation. It is unsupported and should not be used (per Microsoft, e.g. support.microsoft.com/en-us/kb/287515, connect.microsoft.com/SQLServer/Feedback/Details/704389). It can change without warning. Use the XML PATH technique discussed in stackoverflow.com/questions/5031204/… I wrote more here: marc.durdin.net/2015/07/…

                          – Marc Durdin
                          Jul 15 '15 at 0:23










                        67




                        67





                        To be clear, coalesce has nothing to do with creating the list, it just makes sure that NULL values are not included.

                        – Graeme Perrow
                        Feb 13 '09 at 12:02





                        To be clear, coalesce has nothing to do with creating the list, it just makes sure that NULL values are not included.

                        – Graeme Perrow
                        Feb 13 '09 at 12:02




                        16




                        16





                        @Graeme Perrow It doesn't exclude NULL values (a WHERE is required for that -- this will lose results if one of the input values is NULL), and it is required in this approach because: NULL + non-NULL -> NULL and non-NULL + NULL -> NULL; also @Name is NULL by default and, in fact, that property is used as an implicit sentinel here to determine if a ', ' should be added or not.

                        – user166390
                        Aug 15 '10 at 18:57







                        @Graeme Perrow It doesn't exclude NULL values (a WHERE is required for that -- this will lose results if one of the input values is NULL), and it is required in this approach because: NULL + non-NULL -> NULL and non-NULL + NULL -> NULL; also @Name is NULL by default and, in fact, that property is used as an implicit sentinel here to determine if a ', ' should be added or not.

                        – user166390
                        Aug 15 '10 at 18:57






                        58




                        58





                        Please note that this method of concatenation relies on SQL Server executing the query with a particular plan. I have been caught out using this method (with the addition of an ORDER BY). When it was dealing with a small number of rows it worked fine but with more data SQL Server chose a different plan which resulted in selecting the first item with no concatenation whatsoever. See this article by Anith Sen.

                        – fbarber
                        Apr 26 '12 at 2:18





                        Please note that this method of concatenation relies on SQL Server executing the query with a particular plan. I have been caught out using this method (with the addition of an ORDER BY). When it was dealing with a small number of rows it worked fine but with more data SQL Server chose a different plan which resulted in selecting the first item with no concatenation whatsoever. See this article by Anith Sen.

                        – fbarber
                        Apr 26 '12 at 2:18




                        14




                        14





                        This method cannot be used as a sub query in a select list or where-clause, because it use a tSQL variable. In such cases you could use the methods offered by @Ritesh

                        – R. Schreurs
                        Aug 2 '13 at 8:10





                        This method cannot be used as a sub query in a select list or where-clause, because it use a tSQL variable. In such cases you could use the methods offered by @Ritesh

                        – R. Schreurs
                        Aug 2 '13 at 8:10




                        10




                        10





                        This is not a reliable method of concatenation. It is unsupported and should not be used (per Microsoft, e.g. support.microsoft.com/en-us/kb/287515, connect.microsoft.com/SQLServer/Feedback/Details/704389). It can change without warning. Use the XML PATH technique discussed in stackoverflow.com/questions/5031204/… I wrote more here: marc.durdin.net/2015/07/…

                        – Marc Durdin
                        Jul 15 '15 at 0:23







                        This is not a reliable method of concatenation. It is unsupported and should not be used (per Microsoft, e.g. support.microsoft.com/en-us/kb/287515, connect.microsoft.com/SQLServer/Feedback/Details/704389). It can change without warning. Use the XML PATH technique discussed in stackoverflow.com/questions/5031204/… I wrote more here: marc.durdin.net/2015/07/…

                        – Marc Durdin
                        Jul 15 '15 at 0:23













                        326














                        One method not yet shown via the XML data() command in MS SQL Server is:



                        Assume table called NameList with one column called FName,



                        SELECT FName + ', ' AS 'data()' 
                        FROM NameList
                        FOR XML PATH('')


                        returns:



                        "Peter, Paul, Mary, "


                        Only the extra comma must be dealt with.



                        Edit: As adopted from @NReilingh's comment, you can use the following method to remove the trailing comma. Assuming the same table and column names:



                        STUFF(REPLACE((SELECT '#!' + LTRIM(RTRIM(FName)) AS 'data()' FROM NameList
                        FOR XML PATH('')),' #!',', '), 1, 2, '') as Brands





                        share|improve this answer





















                        • 13





                          holy s**t thats amazing! When executed on its own, as in your example the result is formatted as a hyperlink, that when clicked (in SSMS) opens a new window containing the data, but when used as part of a larger query it just appears as a string. Is it a string? or is it xml that i need to treat differently in the application that will be using this data?

                          – Ben
                          Sep 7 '12 at 15:56






                        • 8





                          This approach also XML-escapes characters like < and >. So, SELECTing '<b>' + FName + '</b>' results in "&lt;b&gt;John&lt;/b&gt;&lt;b&gt;Paul..."

                          – Lukáš Lánský
                          Feb 26 '14 at 18:34






                        • 8





                          Neat solution. I am noticing that even when I do not add the + ', ' it still adds a single space between every concatenated element.

                          – Baodad
                          Oct 3 '14 at 22:40






                        • 6





                          @Baodad That appears to be part of the deal. You can workaround by replacing on an added token character. For example, this does a perfect comma-delimited list for any length: SELECT STUFF(REPLACE((SELECT '#!'+city AS 'data()' FROM #cityzip FOR XML PATH ('')),' #!',', '),1,2,'')

                          – NReilingh
                          Feb 29 '16 at 18:12






                        • 1





                          Wow, actually in my testing using data() and a replace is WAY more performant than not. Super weird.

                          – NReilingh
                          Feb 29 '16 at 18:33
















                        326














                        One method not yet shown via the XML data() command in MS SQL Server is:



                        Assume table called NameList with one column called FName,



                        SELECT FName + ', ' AS 'data()' 
                        FROM NameList
                        FOR XML PATH('')


                        returns:



                        "Peter, Paul, Mary, "


                        Only the extra comma must be dealt with.



                        Edit: As adopted from @NReilingh's comment, you can use the following method to remove the trailing comma. Assuming the same table and column names:



                        STUFF(REPLACE((SELECT '#!' + LTRIM(RTRIM(FName)) AS 'data()' FROM NameList
                        FOR XML PATH('')),' #!',', '), 1, 2, '') as Brands





                        share|improve this answer





















                        • 13





                          holy s**t thats amazing! When executed on its own, as in your example the result is formatted as a hyperlink, that when clicked (in SSMS) opens a new window containing the data, but when used as part of a larger query it just appears as a string. Is it a string? or is it xml that i need to treat differently in the application that will be using this data?

                          – Ben
                          Sep 7 '12 at 15:56






                        • 8





                          This approach also XML-escapes characters like < and >. So, SELECTing '<b>' + FName + '</b>' results in "&lt;b&gt;John&lt;/b&gt;&lt;b&gt;Paul..."

                          – Lukáš Lánský
                          Feb 26 '14 at 18:34






                        • 8





                          Neat solution. I am noticing that even when I do not add the + ', ' it still adds a single space between every concatenated element.

                          – Baodad
                          Oct 3 '14 at 22:40






                        • 6





                          @Baodad That appears to be part of the deal. You can workaround by replacing on an added token character. For example, this does a perfect comma-delimited list for any length: SELECT STUFF(REPLACE((SELECT '#!'+city AS 'data()' FROM #cityzip FOR XML PATH ('')),' #!',', '),1,2,'')

                          – NReilingh
                          Feb 29 '16 at 18:12






                        • 1





                          Wow, actually in my testing using data() and a replace is WAY more performant than not. Super weird.

                          – NReilingh
                          Feb 29 '16 at 18:33














                        326












                        326








                        326







                        One method not yet shown via the XML data() command in MS SQL Server is:



                        Assume table called NameList with one column called FName,



                        SELECT FName + ', ' AS 'data()' 
                        FROM NameList
                        FOR XML PATH('')


                        returns:



                        "Peter, Paul, Mary, "


                        Only the extra comma must be dealt with.



                        Edit: As adopted from @NReilingh's comment, you can use the following method to remove the trailing comma. Assuming the same table and column names:



                        STUFF(REPLACE((SELECT '#!' + LTRIM(RTRIM(FName)) AS 'data()' FROM NameList
                        FOR XML PATH('')),' #!',', '), 1, 2, '') as Brands





                        share|improve this answer















                        One method not yet shown via the XML data() command in MS SQL Server is:



                        Assume table called NameList with one column called FName,



                        SELECT FName + ', ' AS 'data()' 
                        FROM NameList
                        FOR XML PATH('')


                        returns:



                        "Peter, Paul, Mary, "


                        Only the extra comma must be dealt with.



                        Edit: As adopted from @NReilingh's comment, you can use the following method to remove the trailing comma. Assuming the same table and column names:



                        STUFF(REPLACE((SELECT '#!' + LTRIM(RTRIM(FName)) AS 'data()' FROM NameList
                        FOR XML PATH('')),' #!',', '), 1, 2, '') as Brands






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Apr 25 '16 at 15:28









                        user1477388

                        13.4k21100202




                        13.4k21100202










                        answered Apr 5 '11 at 21:19









                        jens frandsenjens frandsen

                        3,269192




                        3,269192








                        • 13





                          holy s**t thats amazing! When executed on its own, as in your example the result is formatted as a hyperlink, that when clicked (in SSMS) opens a new window containing the data, but when used as part of a larger query it just appears as a string. Is it a string? or is it xml that i need to treat differently in the application that will be using this data?

                          – Ben
                          Sep 7 '12 at 15:56






                        • 8





                          This approach also XML-escapes characters like < and >. So, SELECTing '<b>' + FName + '</b>' results in "&lt;b&gt;John&lt;/b&gt;&lt;b&gt;Paul..."

                          – Lukáš Lánský
                          Feb 26 '14 at 18:34






                        • 8





                          Neat solution. I am noticing that even when I do not add the + ', ' it still adds a single space between every concatenated element.

                          – Baodad
                          Oct 3 '14 at 22:40






                        • 6





                          @Baodad That appears to be part of the deal. You can workaround by replacing on an added token character. For example, this does a perfect comma-delimited list for any length: SELECT STUFF(REPLACE((SELECT '#!'+city AS 'data()' FROM #cityzip FOR XML PATH ('')),' #!',', '),1,2,'')

                          – NReilingh
                          Feb 29 '16 at 18:12






                        • 1





                          Wow, actually in my testing using data() and a replace is WAY more performant than not. Super weird.

                          – NReilingh
                          Feb 29 '16 at 18:33














                        • 13





                          holy s**t thats amazing! When executed on its own, as in your example the result is formatted as a hyperlink, that when clicked (in SSMS) opens a new window containing the data, but when used as part of a larger query it just appears as a string. Is it a string? or is it xml that i need to treat differently in the application that will be using this data?

                          – Ben
                          Sep 7 '12 at 15:56






                        • 8





                          This approach also XML-escapes characters like < and >. So, SELECTing '<b>' + FName + '</b>' results in "&lt;b&gt;John&lt;/b&gt;&lt;b&gt;Paul..."

                          – Lukáš Lánský
                          Feb 26 '14 at 18:34






                        • 8





                          Neat solution. I am noticing that even when I do not add the + ', ' it still adds a single space between every concatenated element.

                          – Baodad
                          Oct 3 '14 at 22:40






                        • 6





                          @Baodad That appears to be part of the deal. You can workaround by replacing on an added token character. For example, this does a perfect comma-delimited list for any length: SELECT STUFF(REPLACE((SELECT '#!'+city AS 'data()' FROM #cityzip FOR XML PATH ('')),' #!',', '),1,2,'')

                          – NReilingh
                          Feb 29 '16 at 18:12






                        • 1





                          Wow, actually in my testing using data() and a replace is WAY more performant than not. Super weird.

                          – NReilingh
                          Feb 29 '16 at 18:33








                        13




                        13





                        holy s**t thats amazing! When executed on its own, as in your example the result is formatted as a hyperlink, that when clicked (in SSMS) opens a new window containing the data, but when used as part of a larger query it just appears as a string. Is it a string? or is it xml that i need to treat differently in the application that will be using this data?

                        – Ben
                        Sep 7 '12 at 15:56





                        holy s**t thats amazing! When executed on its own, as in your example the result is formatted as a hyperlink, that when clicked (in SSMS) opens a new window containing the data, but when used as part of a larger query it just appears as a string. Is it a string? or is it xml that i need to treat differently in the application that will be using this data?

                        – Ben
                        Sep 7 '12 at 15:56




                        8




                        8





                        This approach also XML-escapes characters like < and >. So, SELECTing '<b>' + FName + '</b>' results in "&lt;b&gt;John&lt;/b&gt;&lt;b&gt;Paul..."

                        – Lukáš Lánský
                        Feb 26 '14 at 18:34





                        This approach also XML-escapes characters like < and >. So, SELECTing '<b>' + FName + '</b>' results in "&lt;b&gt;John&lt;/b&gt;&lt;b&gt;Paul..."

                        – Lukáš Lánský
                        Feb 26 '14 at 18:34




                        8




                        8





                        Neat solution. I am noticing that even when I do not add the + ', ' it still adds a single space between every concatenated element.

                        – Baodad
                        Oct 3 '14 at 22:40





                        Neat solution. I am noticing that even when I do not add the + ', ' it still adds a single space between every concatenated element.

                        – Baodad
                        Oct 3 '14 at 22:40




                        6




                        6





                        @Baodad That appears to be part of the deal. You can workaround by replacing on an added token character. For example, this does a perfect comma-delimited list for any length: SELECT STUFF(REPLACE((SELECT '#!'+city AS 'data()' FROM #cityzip FOR XML PATH ('')),' #!',', '),1,2,'')

                        – NReilingh
                        Feb 29 '16 at 18:12





                        @Baodad That appears to be part of the deal. You can workaround by replacing on an added token character. For example, this does a perfect comma-delimited list for any length: SELECT STUFF(REPLACE((SELECT '#!'+city AS 'data()' FROM #cityzip FOR XML PATH ('')),' #!',', '),1,2,'')

                        – NReilingh
                        Feb 29 '16 at 18:12




                        1




                        1





                        Wow, actually in my testing using data() and a replace is WAY more performant than not. Super weird.

                        – NReilingh
                        Feb 29 '16 at 18:33





                        Wow, actually in my testing using data() and a replace is WAY more performant than not. Super weird.

                        – NReilingh
                        Feb 29 '16 at 18:33











                        265














                        In SQL Server 2005



                        SELECT Stuff(
                        (SELECT N', ' + Name FROM Names FOR XML PATH(''),TYPE)
                        .value('text()[1]','nvarchar(max)'),1,2,N'')




                        In SQL Server 2016



                        you can use the FOR JSON syntax



                        i.e.



                        SELECT per.ID,
                        Emails = JSON_VALUE(
                        REPLACE(
                        (SELECT _ = em.Email FROM Email em WHERE em.Person = per.ID FOR JSON PATH)
                        ,'"},{"_":"',', '),'$[0]._'
                        )
                        FROM Person per


                        And the result will become



                        Id  Emails
                        1 abc@gmail.com
                        2 NULL
                        3 def@gmail.com, xyz@gmail.com


                        This will work even your data contains invalid XML characters



                        the '"},{"_":"' is safe because if you data contain '"},{"_":"', it will be escaped to "},{"_":"



                        You can replace ', ' with any string separator





                        And in SQL Server 2017, Azure SQL Database



                        You can use the new STRING_AGG function






                        share|improve this answer





















                        • 3





                          Good use of the STUFF function to nix the leading two characters.

                          – David
                          Aug 11 '11 at 23:12






                        • 3





                          I like this solution best, because I can easily use it in a select list by appending 'as <label>'. I am not sure how to do this with the solution of @Ritesh.

                          – R. Schreurs
                          Aug 2 '13 at 8:27






                        • 12





                          This is better than the accepted answer because this option also handles un-escaping XML reserverd characters such as <, >, &, etc. which FOR XML PATH('') will automatically escape.

                          – BateTech
                          Apr 7 '14 at 21:35











                        • This is an awesome response as it resolved the issue and provides the best ways of doing things in different versions of SQL now I wish I could use 2017/Azure

                          – Chris Ward
                          May 21 '18 at 14:27
















                        265














                        In SQL Server 2005



                        SELECT Stuff(
                        (SELECT N', ' + Name FROM Names FOR XML PATH(''),TYPE)
                        .value('text()[1]','nvarchar(max)'),1,2,N'')




                        In SQL Server 2016



                        you can use the FOR JSON syntax



                        i.e.



                        SELECT per.ID,
                        Emails = JSON_VALUE(
                        REPLACE(
                        (SELECT _ = em.Email FROM Email em WHERE em.Person = per.ID FOR JSON PATH)
                        ,'"},{"_":"',', '),'$[0]._'
                        )
                        FROM Person per


                        And the result will become



                        Id  Emails
                        1 abc@gmail.com
                        2 NULL
                        3 def@gmail.com, xyz@gmail.com


                        This will work even your data contains invalid XML characters



                        the '"},{"_":"' is safe because if you data contain '"},{"_":"', it will be escaped to "},{"_":"



                        You can replace ', ' with any string separator





                        And in SQL Server 2017, Azure SQL Database



                        You can use the new STRING_AGG function






                        share|improve this answer





















                        • 3





                          Good use of the STUFF function to nix the leading two characters.

                          – David
                          Aug 11 '11 at 23:12






                        • 3





                          I like this solution best, because I can easily use it in a select list by appending 'as <label>'. I am not sure how to do this with the solution of @Ritesh.

                          – R. Schreurs
                          Aug 2 '13 at 8:27






                        • 12





                          This is better than the accepted answer because this option also handles un-escaping XML reserverd characters such as <, >, &, etc. which FOR XML PATH('') will automatically escape.

                          – BateTech
                          Apr 7 '14 at 21:35











                        • This is an awesome response as it resolved the issue and provides the best ways of doing things in different versions of SQL now I wish I could use 2017/Azure

                          – Chris Ward
                          May 21 '18 at 14:27














                        265












                        265








                        265







                        In SQL Server 2005



                        SELECT Stuff(
                        (SELECT N', ' + Name FROM Names FOR XML PATH(''),TYPE)
                        .value('text()[1]','nvarchar(max)'),1,2,N'')




                        In SQL Server 2016



                        you can use the FOR JSON syntax



                        i.e.



                        SELECT per.ID,
                        Emails = JSON_VALUE(
                        REPLACE(
                        (SELECT _ = em.Email FROM Email em WHERE em.Person = per.ID FOR JSON PATH)
                        ,'"},{"_":"',', '),'$[0]._'
                        )
                        FROM Person per


                        And the result will become



                        Id  Emails
                        1 abc@gmail.com
                        2 NULL
                        3 def@gmail.com, xyz@gmail.com


                        This will work even your data contains invalid XML characters



                        the '"},{"_":"' is safe because if you data contain '"},{"_":"', it will be escaped to "},{"_":"



                        You can replace ', ' with any string separator





                        And in SQL Server 2017, Azure SQL Database



                        You can use the new STRING_AGG function






                        share|improve this answer















                        In SQL Server 2005



                        SELECT Stuff(
                        (SELECT N', ' + Name FROM Names FOR XML PATH(''),TYPE)
                        .value('text()[1]','nvarchar(max)'),1,2,N'')




                        In SQL Server 2016



                        you can use the FOR JSON syntax



                        i.e.



                        SELECT per.ID,
                        Emails = JSON_VALUE(
                        REPLACE(
                        (SELECT _ = em.Email FROM Email em WHERE em.Person = per.ID FOR JSON PATH)
                        ,'"},{"_":"',', '),'$[0]._'
                        )
                        FROM Person per


                        And the result will become



                        Id  Emails
                        1 abc@gmail.com
                        2 NULL
                        3 def@gmail.com, xyz@gmail.com


                        This will work even your data contains invalid XML characters



                        the '"},{"_":"' is safe because if you data contain '"},{"_":"', it will be escaped to "},{"_":"



                        You can replace ', ' with any string separator





                        And in SQL Server 2017, Azure SQL Database



                        You can use the new STRING_AGG function







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Jul 23 '18 at 16:55


























                        community wiki





                        9 revs, 7 users 70%
                        Steven Chong









                        • 3





                          Good use of the STUFF function to nix the leading two characters.

                          – David
                          Aug 11 '11 at 23:12






                        • 3





                          I like this solution best, because I can easily use it in a select list by appending 'as <label>'. I am not sure how to do this with the solution of @Ritesh.

                          – R. Schreurs
                          Aug 2 '13 at 8:27






                        • 12





                          This is better than the accepted answer because this option also handles un-escaping XML reserverd characters such as <, >, &, etc. which FOR XML PATH('') will automatically escape.

                          – BateTech
                          Apr 7 '14 at 21:35











                        • This is an awesome response as it resolved the issue and provides the best ways of doing things in different versions of SQL now I wish I could use 2017/Azure

                          – Chris Ward
                          May 21 '18 at 14:27














                        • 3





                          Good use of the STUFF function to nix the leading two characters.

                          – David
                          Aug 11 '11 at 23:12






                        • 3





                          I like this solution best, because I can easily use it in a select list by appending 'as <label>'. I am not sure how to do this with the solution of @Ritesh.

                          – R. Schreurs
                          Aug 2 '13 at 8:27






                        • 12





                          This is better than the accepted answer because this option also handles un-escaping XML reserverd characters such as <, >, &, etc. which FOR XML PATH('') will automatically escape.

                          – BateTech
                          Apr 7 '14 at 21:35











                        • This is an awesome response as it resolved the issue and provides the best ways of doing things in different versions of SQL now I wish I could use 2017/Azure

                          – Chris Ward
                          May 21 '18 at 14:27








                        3




                        3





                        Good use of the STUFF function to nix the leading two characters.

                        – David
                        Aug 11 '11 at 23:12





                        Good use of the STUFF function to nix the leading two characters.

                        – David
                        Aug 11 '11 at 23:12




                        3




                        3





                        I like this solution best, because I can easily use it in a select list by appending 'as <label>'. I am not sure how to do this with the solution of @Ritesh.

                        – R. Schreurs
                        Aug 2 '13 at 8:27





                        I like this solution best, because I can easily use it in a select list by appending 'as <label>'. I am not sure how to do this with the solution of @Ritesh.

                        – R. Schreurs
                        Aug 2 '13 at 8:27




                        12




                        12





                        This is better than the accepted answer because this option also handles un-escaping XML reserverd characters such as <, >, &, etc. which FOR XML PATH('') will automatically escape.

                        – BateTech
                        Apr 7 '14 at 21:35





                        This is better than the accepted answer because this option also handles un-escaping XML reserverd characters such as <, >, &, etc. which FOR XML PATH('') will automatically escape.

                        – BateTech
                        Apr 7 '14 at 21:35













                        This is an awesome response as it resolved the issue and provides the best ways of doing things in different versions of SQL now I wish I could use 2017/Azure

                        – Chris Ward
                        May 21 '18 at 14:27





                        This is an awesome response as it resolved the issue and provides the best ways of doing things in different versions of SQL now I wish I could use 2017/Azure

                        – Chris Ward
                        May 21 '18 at 14:27











                        265





                        +150









                        SQL Server 2017+ and SQL Azure: STRING_AGG



                        Starting with the next version of SQL Server, we can finally concatenate across rows without having to resort to any variable or XML witchery.



                        STRING_AGG (Transact-SQL)



                        Without grouping



                        SELECT STRING_AGG(Name, ', ') AS Departments
                        FROM HumanResources.Department;


                        With grouping :



                        SELECT GroupName, STRING_AGG(Name, ', ') AS Departments
                        FROM HumanResources.Department
                        GROUP BY GroupName;


                        With grouping and sub-sorting



                        SELECT GroupName, STRING_AGG(Name, ', ') WITHIN GROUP (ORDER BY Name ASC) AS Departments
                        FROM HumanResources.Department
                        GROUP BY GroupName;





                        share|improve this answer





















                        • 1





                          And, unlike CLR solutions, you have control over the sorting.

                          – canon
                          Jul 10 '17 at 16:17






                        • 2





                          This works with SQL Azure. Great answer!

                          – user2721607
                          Oct 11 '17 at 20:27






                        • 2





                          This also worked for me in Azure SQL. Brilliant!

                          – Kevin Stone
                          Jan 4 '18 at 20:31
















                        265





                        +150









                        SQL Server 2017+ and SQL Azure: STRING_AGG



                        Starting with the next version of SQL Server, we can finally concatenate across rows without having to resort to any variable or XML witchery.



                        STRING_AGG (Transact-SQL)



                        Without grouping



                        SELECT STRING_AGG(Name, ', ') AS Departments
                        FROM HumanResources.Department;


                        With grouping :



                        SELECT GroupName, STRING_AGG(Name, ', ') AS Departments
                        FROM HumanResources.Department
                        GROUP BY GroupName;


                        With grouping and sub-sorting



                        SELECT GroupName, STRING_AGG(Name, ', ') WITHIN GROUP (ORDER BY Name ASC) AS Departments
                        FROM HumanResources.Department
                        GROUP BY GroupName;





                        share|improve this answer





















                        • 1





                          And, unlike CLR solutions, you have control over the sorting.

                          – canon
                          Jul 10 '17 at 16:17






                        • 2





                          This works with SQL Azure. Great answer!

                          – user2721607
                          Oct 11 '17 at 20:27






                        • 2





                          This also worked for me in Azure SQL. Brilliant!

                          – Kevin Stone
                          Jan 4 '18 at 20:31














                        265





                        +150







                        265





                        +150



                        265




                        +150





                        SQL Server 2017+ and SQL Azure: STRING_AGG



                        Starting with the next version of SQL Server, we can finally concatenate across rows without having to resort to any variable or XML witchery.



                        STRING_AGG (Transact-SQL)



                        Without grouping



                        SELECT STRING_AGG(Name, ', ') AS Departments
                        FROM HumanResources.Department;


                        With grouping :



                        SELECT GroupName, STRING_AGG(Name, ', ') AS Departments
                        FROM HumanResources.Department
                        GROUP BY GroupName;


                        With grouping and sub-sorting



                        SELECT GroupName, STRING_AGG(Name, ', ') WITHIN GROUP (ORDER BY Name ASC) AS Departments
                        FROM HumanResources.Department
                        GROUP BY GroupName;





                        share|improve this answer















                        SQL Server 2017+ and SQL Azure: STRING_AGG



                        Starting with the next version of SQL Server, we can finally concatenate across rows without having to resort to any variable or XML witchery.



                        STRING_AGG (Transact-SQL)



                        Without grouping



                        SELECT STRING_AGG(Name, ', ') AS Departments
                        FROM HumanResources.Department;


                        With grouping :



                        SELECT GroupName, STRING_AGG(Name, ', ') AS Departments
                        FROM HumanResources.Department
                        GROUP BY GroupName;


                        With grouping and sub-sorting



                        SELECT GroupName, STRING_AGG(Name, ', ') WITHIN GROUP (ORDER BY Name ASC) AS Departments
                        FROM HumanResources.Department
                        GROUP BY GroupName;






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Jul 24 '18 at 5:36

























                        answered Mar 14 '17 at 5:00









                        Mathieu RendaMathieu Renda

                        4,58311528




                        4,58311528








                        • 1





                          And, unlike CLR solutions, you have control over the sorting.

                          – canon
                          Jul 10 '17 at 16:17






                        • 2





                          This works with SQL Azure. Great answer!

                          – user2721607
                          Oct 11 '17 at 20:27






                        • 2





                          This also worked for me in Azure SQL. Brilliant!

                          – Kevin Stone
                          Jan 4 '18 at 20:31














                        • 1





                          And, unlike CLR solutions, you have control over the sorting.

                          – canon
                          Jul 10 '17 at 16:17






                        • 2





                          This works with SQL Azure. Great answer!

                          – user2721607
                          Oct 11 '17 at 20:27






                        • 2





                          This also worked for me in Azure SQL. Brilliant!

                          – Kevin Stone
                          Jan 4 '18 at 20:31








                        1




                        1





                        And, unlike CLR solutions, you have control over the sorting.

                        – canon
                        Jul 10 '17 at 16:17





                        And, unlike CLR solutions, you have control over the sorting.

                        – canon
                        Jul 10 '17 at 16:17




                        2




                        2





                        This works with SQL Azure. Great answer!

                        – user2721607
                        Oct 11 '17 at 20:27





                        This works with SQL Azure. Great answer!

                        – user2721607
                        Oct 11 '17 at 20:27




                        2




                        2





                        This also worked for me in Azure SQL. Brilliant!

                        – Kevin Stone
                        Jan 4 '18 at 20:31





                        This also worked for me in Azure SQL. Brilliant!

                        – Kevin Stone
                        Jan 4 '18 at 20:31











                        111














                        In MySQL there is a function, GROUP_CONCAT(), which allows you to concatenate the values from multiple rows. Example:



                        SELECT 1 AS a, GROUP_CONCAT(name ORDER BY name ASC SEPARATOR ', ') AS people 
                        FROM users
                        WHERE id IN (1,2,3)
                        GROUP BY a





                        share|improve this answer





















                        • 2





                          Used to love this one, have not seen a alternative to this function with any other Db yet!

                          – Binoj Antony
                          Jun 18 '09 at 6:05






                        • 1





                          This totally solved my problem. I was trying to pull all the payment dates for a given charge on an account, this solved it perfectly. Thanks!

                          – Maximus
                          Aug 26 '16 at 15:47











                        • works well. But when i use SEPARATOR '", "' i'll miss some chars at the end of the last entry. why can this happen?

                          – gooleem
                          Nov 27 '16 at 13:05











                        • @gooleem I'm not clear on what you mean, but this function only puts the separator between items, not after. If that's not the answer, I'd recommend posting a new question.

                          – Darryl Hein
                          Dec 4 '16 at 23:41











                        • @DarrylHein for my needs i used the separator as above. But this cuts me some chars at the very end of the output. This is very strange and seems to be a bug. I dont have a solution, i just workedaround.

                          – gooleem
                          Dec 6 '16 at 9:28


















                        111














                        In MySQL there is a function, GROUP_CONCAT(), which allows you to concatenate the values from multiple rows. Example:



                        SELECT 1 AS a, GROUP_CONCAT(name ORDER BY name ASC SEPARATOR ', ') AS people 
                        FROM users
                        WHERE id IN (1,2,3)
                        GROUP BY a





                        share|improve this answer





















                        • 2





                          Used to love this one, have not seen a alternative to this function with any other Db yet!

                          – Binoj Antony
                          Jun 18 '09 at 6:05






                        • 1





                          This totally solved my problem. I was trying to pull all the payment dates for a given charge on an account, this solved it perfectly. Thanks!

                          – Maximus
                          Aug 26 '16 at 15:47











                        • works well. But when i use SEPARATOR '", "' i'll miss some chars at the end of the last entry. why can this happen?

                          – gooleem
                          Nov 27 '16 at 13:05











                        • @gooleem I'm not clear on what you mean, but this function only puts the separator between items, not after. If that's not the answer, I'd recommend posting a new question.

                          – Darryl Hein
                          Dec 4 '16 at 23:41











                        • @DarrylHein for my needs i used the separator as above. But this cuts me some chars at the very end of the output. This is very strange and seems to be a bug. I dont have a solution, i just workedaround.

                          – gooleem
                          Dec 6 '16 at 9:28
















                        111












                        111








                        111







                        In MySQL there is a function, GROUP_CONCAT(), which allows you to concatenate the values from multiple rows. Example:



                        SELECT 1 AS a, GROUP_CONCAT(name ORDER BY name ASC SEPARATOR ', ') AS people 
                        FROM users
                        WHERE id IN (1,2,3)
                        GROUP BY a





                        share|improve this answer















                        In MySQL there is a function, GROUP_CONCAT(), which allows you to concatenate the values from multiple rows. Example:



                        SELECT 1 AS a, GROUP_CONCAT(name ORDER BY name ASC SEPARATOR ', ') AS people 
                        FROM users
                        WHERE id IN (1,2,3)
                        GROUP BY a






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Feb 26 '12 at 18:37









                        Peter Mortensen

                        13.9k1987113




                        13.9k1987113










                        answered Oct 12 '08 at 0:10









                        Darryl HeinDarryl Hein

                        69.7k83191245




                        69.7k83191245








                        • 2





                          Used to love this one, have not seen a alternative to this function with any other Db yet!

                          – Binoj Antony
                          Jun 18 '09 at 6:05






                        • 1





                          This totally solved my problem. I was trying to pull all the payment dates for a given charge on an account, this solved it perfectly. Thanks!

                          – Maximus
                          Aug 26 '16 at 15:47











                        • works well. But when i use SEPARATOR '", "' i'll miss some chars at the end of the last entry. why can this happen?

                          – gooleem
                          Nov 27 '16 at 13:05











                        • @gooleem I'm not clear on what you mean, but this function only puts the separator between items, not after. If that's not the answer, I'd recommend posting a new question.

                          – Darryl Hein
                          Dec 4 '16 at 23:41











                        • @DarrylHein for my needs i used the separator as above. But this cuts me some chars at the very end of the output. This is very strange and seems to be a bug. I dont have a solution, i just workedaround.

                          – gooleem
                          Dec 6 '16 at 9:28
















                        • 2





                          Used to love this one, have not seen a alternative to this function with any other Db yet!

                          – Binoj Antony
                          Jun 18 '09 at 6:05






                        • 1





                          This totally solved my problem. I was trying to pull all the payment dates for a given charge on an account, this solved it perfectly. Thanks!

                          – Maximus
                          Aug 26 '16 at 15:47











                        • works well. But when i use SEPARATOR '", "' i'll miss some chars at the end of the last entry. why can this happen?

                          – gooleem
                          Nov 27 '16 at 13:05











                        • @gooleem I'm not clear on what you mean, but this function only puts the separator between items, not after. If that's not the answer, I'd recommend posting a new question.

                          – Darryl Hein
                          Dec 4 '16 at 23:41











                        • @DarrylHein for my needs i used the separator as above. But this cuts me some chars at the very end of the output. This is very strange and seems to be a bug. I dont have a solution, i just workedaround.

                          – gooleem
                          Dec 6 '16 at 9:28










                        2




                        2





                        Used to love this one, have not seen a alternative to this function with any other Db yet!

                        – Binoj Antony
                        Jun 18 '09 at 6:05





                        Used to love this one, have not seen a alternative to this function with any other Db yet!

                        – Binoj Antony
                        Jun 18 '09 at 6:05




                        1




                        1





                        This totally solved my problem. I was trying to pull all the payment dates for a given charge on an account, this solved it perfectly. Thanks!

                        – Maximus
                        Aug 26 '16 at 15:47





                        This totally solved my problem. I was trying to pull all the payment dates for a given charge on an account, this solved it perfectly. Thanks!

                        – Maximus
                        Aug 26 '16 at 15:47













                        works well. But when i use SEPARATOR '", "' i'll miss some chars at the end of the last entry. why can this happen?

                        – gooleem
                        Nov 27 '16 at 13:05





                        works well. But when i use SEPARATOR '", "' i'll miss some chars at the end of the last entry. why can this happen?

                        – gooleem
                        Nov 27 '16 at 13:05













                        @gooleem I'm not clear on what you mean, but this function only puts the separator between items, not after. If that's not the answer, I'd recommend posting a new question.

                        – Darryl Hein
                        Dec 4 '16 at 23:41





                        @gooleem I'm not clear on what you mean, but this function only puts the separator between items, not after. If that's not the answer, I'd recommend posting a new question.

                        – Darryl Hein
                        Dec 4 '16 at 23:41













                        @DarrylHein for my needs i used the separator as above. But this cuts me some chars at the very end of the output. This is very strange and seems to be a bug. I dont have a solution, i just workedaround.

                        – gooleem
                        Dec 6 '16 at 9:28







                        @DarrylHein for my needs i used the separator as above. But this cuts me some chars at the very end of the output. This is very strange and seems to be a bug. I dont have a solution, i just workedaround.

                        – gooleem
                        Dec 6 '16 at 9:28













                        52














                        Use COALESCE - Learn more from here



                        For an example:




                        102



                        103



                        104




                        Then write below code in sql server,



                        Declare @Numbers AS Nvarchar(MAX) -- It must not be MAX if you have few numbers 
                        SELECT @Numbers = COALESCE(@Numbers + ',', '') + Number
                        FROM TableName where Number IS NOT NULL

                        SELECT @Numbers


                        Output would be:



                        102,103,104





                        share|improve this answer





















                        • 2





                          This is really the best solution IMO as it avoids the encoding issues that FOR XML presents. I used Declare @Numbers AS Nvarchar(MAX) and it worked fine. Can you explain why you recommend not using it please?

                          – EvilDr
                          Aug 3 '16 at 15:01






                        • 6





                          This solution has already been posted 8 years ago! stackoverflow.com/a/194887/986862

                          – Andre Figueiredo
                          May 3 '17 at 21:53











                        • Why is this query returns ??? symbols instead of Cyrillic ones? Is this just output issue?

                          – Akmal Salikhov
                          Dec 7 '17 at 11:31
















                        52














                        Use COALESCE - Learn more from here



                        For an example:




                        102



                        103



                        104




                        Then write below code in sql server,



                        Declare @Numbers AS Nvarchar(MAX) -- It must not be MAX if you have few numbers 
                        SELECT @Numbers = COALESCE(@Numbers + ',', '') + Number
                        FROM TableName where Number IS NOT NULL

                        SELECT @Numbers


                        Output would be:



                        102,103,104





                        share|improve this answer





















                        • 2





                          This is really the best solution IMO as it avoids the encoding issues that FOR XML presents. I used Declare @Numbers AS Nvarchar(MAX) and it worked fine. Can you explain why you recommend not using it please?

                          – EvilDr
                          Aug 3 '16 at 15:01






                        • 6





                          This solution has already been posted 8 years ago! stackoverflow.com/a/194887/986862

                          – Andre Figueiredo
                          May 3 '17 at 21:53











                        • Why is this query returns ??? symbols instead of Cyrillic ones? Is this just output issue?

                          – Akmal Salikhov
                          Dec 7 '17 at 11:31














                        52












                        52








                        52







                        Use COALESCE - Learn more from here



                        For an example:




                        102



                        103



                        104




                        Then write below code in sql server,



                        Declare @Numbers AS Nvarchar(MAX) -- It must not be MAX if you have few numbers 
                        SELECT @Numbers = COALESCE(@Numbers + ',', '') + Number
                        FROM TableName where Number IS NOT NULL

                        SELECT @Numbers


                        Output would be:



                        102,103,104





                        share|improve this answer















                        Use COALESCE - Learn more from here



                        For an example:




                        102



                        103



                        104




                        Then write below code in sql server,



                        Declare @Numbers AS Nvarchar(MAX) -- It must not be MAX if you have few numbers 
                        SELECT @Numbers = COALESCE(@Numbers + ',', '') + Number
                        FROM TableName where Number IS NOT NULL

                        SELECT @Numbers


                        Output would be:



                        102,103,104






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Sep 22 '17 at 23:27









                        Graham

                        3,868143860




                        3,868143860










                        answered Apr 5 '16 at 7:08









                        pedrampedram

                        5,05664166




                        5,05664166








                        • 2





                          This is really the best solution IMO as it avoids the encoding issues that FOR XML presents. I used Declare @Numbers AS Nvarchar(MAX) and it worked fine. Can you explain why you recommend not using it please?

                          – EvilDr
                          Aug 3 '16 at 15:01






                        • 6





                          This solution has already been posted 8 years ago! stackoverflow.com/a/194887/986862

                          – Andre Figueiredo
                          May 3 '17 at 21:53











                        • Why is this query returns ??? symbols instead of Cyrillic ones? Is this just output issue?

                          – Akmal Salikhov
                          Dec 7 '17 at 11:31














                        • 2





                          This is really the best solution IMO as it avoids the encoding issues that FOR XML presents. I used Declare @Numbers AS Nvarchar(MAX) and it worked fine. Can you explain why you recommend not using it please?

                          – EvilDr
                          Aug 3 '16 at 15:01






                        • 6





                          This solution has already been posted 8 years ago! stackoverflow.com/a/194887/986862

                          – Andre Figueiredo
                          May 3 '17 at 21:53











                        • Why is this query returns ??? symbols instead of Cyrillic ones? Is this just output issue?

                          – Akmal Salikhov
                          Dec 7 '17 at 11:31








                        2




                        2





                        This is really the best solution IMO as it avoids the encoding issues that FOR XML presents. I used Declare @Numbers AS Nvarchar(MAX) and it worked fine. Can you explain why you recommend not using it please?

                        – EvilDr
                        Aug 3 '16 at 15:01





                        This is really the best solution IMO as it avoids the encoding issues that FOR XML presents. I used Declare @Numbers AS Nvarchar(MAX) and it worked fine. Can you explain why you recommend not using it please?

                        – EvilDr
                        Aug 3 '16 at 15:01




                        6




                        6





                        This solution has already been posted 8 years ago! stackoverflow.com/a/194887/986862

                        – Andre Figueiredo
                        May 3 '17 at 21:53





                        This solution has already been posted 8 years ago! stackoverflow.com/a/194887/986862

                        – Andre Figueiredo
                        May 3 '17 at 21:53













                        Why is this query returns ??? symbols instead of Cyrillic ones? Is this just output issue?

                        – Akmal Salikhov
                        Dec 7 '17 at 11:31





                        Why is this query returns ??? symbols instead of Cyrillic ones? Is this just output issue?

                        – Akmal Salikhov
                        Dec 7 '17 at 11:31











                        47














                        Postgres arrays are awesome. Example:



                        Create some test data:



                        postgres=# c test
                        You are now connected to database "test" as user "hgimenez".
                        test=# create table names (name text);
                        CREATE TABLE
                        test=# insert into names (name) values ('Peter'), ('Paul'), ('Mary');
                        INSERT 0 3
                        test=# select * from names;
                        name
                        -------
                        Peter
                        Paul
                        Mary
                        (3 rows)


                        Aggregate them in an array:



                        test=# select array_agg(name) from names;
                        array_agg
                        -------------------
                        {Peter,Paul,Mary}
                        (1 row)


                        Convert the array to a comma delimited string:



                        test=# select array_to_string(array_agg(name), ', ') from names;
                        array_to_string
                        -------------------
                        Peter, Paul, Mary
                        (1 row)


                        DONE



                        Since PostgreSQL 9.0 it is even easier.






                        share|improve this answer


























                        • If you need more than one column, for example their employee id in brackets use the concat operator: select array_to_string(array_agg(name||'('||id||')'

                          – Richard Fox
                          Feb 27 '15 at 11:50











                        • Not applicable to sql-server, only to mysql

                          – GoldBishop
                          May 4 '17 at 15:03
















                        47














                        Postgres arrays are awesome. Example:



                        Create some test data:



                        postgres=# c test
                        You are now connected to database "test" as user "hgimenez".
                        test=# create table names (name text);
                        CREATE TABLE
                        test=# insert into names (name) values ('Peter'), ('Paul'), ('Mary');
                        INSERT 0 3
                        test=# select * from names;
                        name
                        -------
                        Peter
                        Paul
                        Mary
                        (3 rows)


                        Aggregate them in an array:



                        test=# select array_agg(name) from names;
                        array_agg
                        -------------------
                        {Peter,Paul,Mary}
                        (1 row)


                        Convert the array to a comma delimited string:



                        test=# select array_to_string(array_agg(name), ', ') from names;
                        array_to_string
                        -------------------
                        Peter, Paul, Mary
                        (1 row)


                        DONE



                        Since PostgreSQL 9.0 it is even easier.






                        share|improve this answer


























                        • If you need more than one column, for example their employee id in brackets use the concat operator: select array_to_string(array_agg(name||'('||id||')'

                          – Richard Fox
                          Feb 27 '15 at 11:50











                        • Not applicable to sql-server, only to mysql

                          – GoldBishop
                          May 4 '17 at 15:03














                        47












                        47








                        47







                        Postgres arrays are awesome. Example:



                        Create some test data:



                        postgres=# c test
                        You are now connected to database "test" as user "hgimenez".
                        test=# create table names (name text);
                        CREATE TABLE
                        test=# insert into names (name) values ('Peter'), ('Paul'), ('Mary');
                        INSERT 0 3
                        test=# select * from names;
                        name
                        -------
                        Peter
                        Paul
                        Mary
                        (3 rows)


                        Aggregate them in an array:



                        test=# select array_agg(name) from names;
                        array_agg
                        -------------------
                        {Peter,Paul,Mary}
                        (1 row)


                        Convert the array to a comma delimited string:



                        test=# select array_to_string(array_agg(name), ', ') from names;
                        array_to_string
                        -------------------
                        Peter, Paul, Mary
                        (1 row)


                        DONE



                        Since PostgreSQL 9.0 it is even easier.






                        share|improve this answer















                        Postgres arrays are awesome. Example:



                        Create some test data:



                        postgres=# c test
                        You are now connected to database "test" as user "hgimenez".
                        test=# create table names (name text);
                        CREATE TABLE
                        test=# insert into names (name) values ('Peter'), ('Paul'), ('Mary');
                        INSERT 0 3
                        test=# select * from names;
                        name
                        -------
                        Peter
                        Paul
                        Mary
                        (3 rows)


                        Aggregate them in an array:



                        test=# select array_agg(name) from names;
                        array_agg
                        -------------------
                        {Peter,Paul,Mary}
                        (1 row)


                        Convert the array to a comma delimited string:



                        test=# select array_to_string(array_agg(name), ', ') from names;
                        array_to_string
                        -------------------
                        Peter, Paul, Mary
                        (1 row)


                        DONE



                        Since PostgreSQL 9.0 it is even easier.







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited May 23 '17 at 12:18









                        Community

                        11




                        11










                        answered Aug 9 '12 at 21:20









                        hgmnzhgmnz

                        11.8k33239




                        11.8k33239













                        • If you need more than one column, for example their employee id in brackets use the concat operator: select array_to_string(array_agg(name||'('||id||')'

                          – Richard Fox
                          Feb 27 '15 at 11:50











                        • Not applicable to sql-server, only to mysql

                          – GoldBishop
                          May 4 '17 at 15:03



















                        • If you need more than one column, for example their employee id in brackets use the concat operator: select array_to_string(array_agg(name||'('||id||')'

                          – Richard Fox
                          Feb 27 '15 at 11:50











                        • Not applicable to sql-server, only to mysql

                          – GoldBishop
                          May 4 '17 at 15:03

















                        If you need more than one column, for example their employee id in brackets use the concat operator: select array_to_string(array_agg(name||'('||id||')'

                        – Richard Fox
                        Feb 27 '15 at 11:50





                        If you need more than one column, for example their employee id in brackets use the concat operator: select array_to_string(array_agg(name||'('||id||')'

                        – Richard Fox
                        Feb 27 '15 at 11:50













                        Not applicable to sql-server, only to mysql

                        – GoldBishop
                        May 4 '17 at 15:03





                        Not applicable to sql-server, only to mysql

                        – GoldBishop
                        May 4 '17 at 15:03











                        45














                        Oracle 11g Release 2 supports the LISTAGG function. Documentation here.



                        COLUMN employees FORMAT A50

                        SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
                        FROM emp
                        GROUP BY deptno;

                        DEPTNO EMPLOYEES
                        ---------- --------------------------------------------------
                        10 CLARK,KING,MILLER
                        20 ADAMS,FORD,JONES,SCOTT,SMITH
                        30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

                        3 rows selected.


                        Warning



                        Be careful implementing this function if there is possibility of the resulting string going over 4000 characters. It will throw an exception. If that's the case then you need to either handle the exception or roll your own function that prevents the joined string from going over 4000 characters.






                        share|improve this answer





















                        • 1





                          For older versions of Oracle, wm_concat is perfect. Its use is explained in the link gift by Alex. Thnks Alex!

                          – toscanelli
                          Jul 20 '15 at 13:04











                        • LISTAGG works perfect! Just read the document linked here. wm_concat removed from version 12c onwards.

                          – asgs
                          Jun 22 '16 at 18:56


















                        45














                        Oracle 11g Release 2 supports the LISTAGG function. Documentation here.



                        COLUMN employees FORMAT A50

                        SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
                        FROM emp
                        GROUP BY deptno;

                        DEPTNO EMPLOYEES
                        ---------- --------------------------------------------------
                        10 CLARK,KING,MILLER
                        20 ADAMS,FORD,JONES,SCOTT,SMITH
                        30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

                        3 rows selected.


                        Warning



                        Be careful implementing this function if there is possibility of the resulting string going over 4000 characters. It will throw an exception. If that's the case then you need to either handle the exception or roll your own function that prevents the joined string from going over 4000 characters.






                        share|improve this answer





















                        • 1





                          For older versions of Oracle, wm_concat is perfect. Its use is explained in the link gift by Alex. Thnks Alex!

                          – toscanelli
                          Jul 20 '15 at 13:04











                        • LISTAGG works perfect! Just read the document linked here. wm_concat removed from version 12c onwards.

                          – asgs
                          Jun 22 '16 at 18:56
















                        45












                        45








                        45







                        Oracle 11g Release 2 supports the LISTAGG function. Documentation here.



                        COLUMN employees FORMAT A50

                        SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
                        FROM emp
                        GROUP BY deptno;

                        DEPTNO EMPLOYEES
                        ---------- --------------------------------------------------
                        10 CLARK,KING,MILLER
                        20 ADAMS,FORD,JONES,SCOTT,SMITH
                        30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

                        3 rows selected.


                        Warning



                        Be careful implementing this function if there is possibility of the resulting string going over 4000 characters. It will throw an exception. If that's the case then you need to either handle the exception or roll your own function that prevents the joined string from going over 4000 characters.






                        share|improve this answer















                        Oracle 11g Release 2 supports the LISTAGG function. Documentation here.



                        COLUMN employees FORMAT A50

                        SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
                        FROM emp
                        GROUP BY deptno;

                        DEPTNO EMPLOYEES
                        ---------- --------------------------------------------------
                        10 CLARK,KING,MILLER
                        20 ADAMS,FORD,JONES,SCOTT,SMITH
                        30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

                        3 rows selected.


                        Warning



                        Be careful implementing this function if there is possibility of the resulting string going over 4000 characters. It will throw an exception. If that's the case then you need to either handle the exception or roll your own function that prevents the joined string from going over 4000 characters.







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Mar 14 '13 at 14:30

























                        answered Mar 8 '12 at 16:29









                        AlexAlex

                        7,24875875




                        7,24875875








                        • 1





                          For older versions of Oracle, wm_concat is perfect. Its use is explained in the link gift by Alex. Thnks Alex!

                          – toscanelli
                          Jul 20 '15 at 13:04











                        • LISTAGG works perfect! Just read the document linked here. wm_concat removed from version 12c onwards.

                          – asgs
                          Jun 22 '16 at 18:56
















                        • 1





                          For older versions of Oracle, wm_concat is perfect. Its use is explained in the link gift by Alex. Thnks Alex!

                          – toscanelli
                          Jul 20 '15 at 13:04











                        • LISTAGG works perfect! Just read the document linked here. wm_concat removed from version 12c onwards.

                          – asgs
                          Jun 22 '16 at 18:56










                        1




                        1





                        For older versions of Oracle, wm_concat is perfect. Its use is explained in the link gift by Alex. Thnks Alex!

                        – toscanelli
                        Jul 20 '15 at 13:04





                        For older versions of Oracle, wm_concat is perfect. Its use is explained in the link gift by Alex. Thnks Alex!

                        – toscanelli
                        Jul 20 '15 at 13:04













                        LISTAGG works perfect! Just read the document linked here. wm_concat removed from version 12c onwards.

                        – asgs
                        Jun 22 '16 at 18:56







                        LISTAGG works perfect! Just read the document linked here. wm_concat removed from version 12c onwards.

                        – asgs
                        Jun 22 '16 at 18:56













                        32














                        In SQL Server 2005 and later, use the query below to concatenate the rows.



                        DECLARE @t table
                        (
                        Id int,
                        Name varchar(10)
                        )
                        INSERT INTO @t
                        SELECT 1,'a' UNION ALL
                        SELECT 1,'b' UNION ALL
                        SELECT 2,'c' UNION ALL
                        SELECT 2,'d'

                        SELECT ID,
                        stuff(
                        (
                        SELECT ','+ [Name] FROM @t WHERE Id = t.Id FOR XML PATH('')
                        ),1,1,'')
                        FROM (SELECT DISTINCT ID FROM @t ) t





                        share|improve this answer





















                        • 2





                          I believe this fails when the values contain XML symbols such as < or &.

                          – Sam
                          Aug 13 '13 at 1:36
















                        32














                        In SQL Server 2005 and later, use the query below to concatenate the rows.



                        DECLARE @t table
                        (
                        Id int,
                        Name varchar(10)
                        )
                        INSERT INTO @t
                        SELECT 1,'a' UNION ALL
                        SELECT 1,'b' UNION ALL
                        SELECT 2,'c' UNION ALL
                        SELECT 2,'d'

                        SELECT ID,
                        stuff(
                        (
                        SELECT ','+ [Name] FROM @t WHERE Id = t.Id FOR XML PATH('')
                        ),1,1,'')
                        FROM (SELECT DISTINCT ID FROM @t ) t





                        share|improve this answer





















                        • 2





                          I believe this fails when the values contain XML symbols such as < or &.

                          – Sam
                          Aug 13 '13 at 1:36














                        32












                        32








                        32







                        In SQL Server 2005 and later, use the query below to concatenate the rows.



                        DECLARE @t table
                        (
                        Id int,
                        Name varchar(10)
                        )
                        INSERT INTO @t
                        SELECT 1,'a' UNION ALL
                        SELECT 1,'b' UNION ALL
                        SELECT 2,'c' UNION ALL
                        SELECT 2,'d'

                        SELECT ID,
                        stuff(
                        (
                        SELECT ','+ [Name] FROM @t WHERE Id = t.Id FOR XML PATH('')
                        ),1,1,'')
                        FROM (SELECT DISTINCT ID FROM @t ) t





                        share|improve this answer















                        In SQL Server 2005 and later, use the query below to concatenate the rows.



                        DECLARE @t table
                        (
                        Id int,
                        Name varchar(10)
                        )
                        INSERT INTO @t
                        SELECT 1,'a' UNION ALL
                        SELECT 1,'b' UNION ALL
                        SELECT 2,'c' UNION ALL
                        SELECT 2,'d'

                        SELECT ID,
                        stuff(
                        (
                        SELECT ','+ [Name] FROM @t WHERE Id = t.Id FOR XML PATH('')
                        ),1,1,'')
                        FROM (SELECT DISTINCT ID FROM @t ) t






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Oct 20 '14 at 8:49









                        George Garchagudashvili

                        5,305123350




                        5,305123350










                        answered Jul 6 '11 at 12:46









                        Yogesh BhadauiryaYogesh Bhadauirya

                        1,145810




                        1,145810








                        • 2





                          I believe this fails when the values contain XML symbols such as < or &.

                          – Sam
                          Aug 13 '13 at 1:36














                        • 2





                          I believe this fails when the values contain XML symbols such as < or &.

                          – Sam
                          Aug 13 '13 at 1:36








                        2




                        2





                        I believe this fails when the values contain XML symbols such as < or &.

                        – Sam
                        Aug 13 '13 at 1:36





                        I believe this fails when the values contain XML symbols such as < or &.

                        – Sam
                        Aug 13 '13 at 1:36











                        27














                        I don't have access to a SQL Server at home, so I'm guess at the syntax here, but it's more or less:



                        DECLARE @names VARCHAR(500)

                        SELECT @names = @names + ' ' + Name
                        FROM Names





                        share|improve this answer



















                        • 10





                          You'd need to init @names to something non-null, otherwise you will get NULL throughout; you'd also need to handle the delimiter (including the unnecessary one)

                          – Marc Gravell
                          Oct 12 '08 at 9:10






                        • 3





                          the only problem with this approach (which i use all the time) is that you can't embed it

                          – ekkis
                          Nov 23 '12 at 22:22











                        • To get rid of the leading space change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ' ' END + Name FROM Names

                          – Tian van Heerden
                          Mar 4 '16 at 9:15













                        • Also, you have to check that Name is not null, you can do it by doing: SELECT @names = @names + ISNULL(' ' + Name, '')

                          – Vita1ij
                          Mar 18 '16 at 10:49
















                        27














                        I don't have access to a SQL Server at home, so I'm guess at the syntax here, but it's more or less:



                        DECLARE @names VARCHAR(500)

                        SELECT @names = @names + ' ' + Name
                        FROM Names





                        share|improve this answer



















                        • 10





                          You'd need to init @names to something non-null, otherwise you will get NULL throughout; you'd also need to handle the delimiter (including the unnecessary one)

                          – Marc Gravell
                          Oct 12 '08 at 9:10






                        • 3





                          the only problem with this approach (which i use all the time) is that you can't embed it

                          – ekkis
                          Nov 23 '12 at 22:22











                        • To get rid of the leading space change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ' ' END + Name FROM Names

                          – Tian van Heerden
                          Mar 4 '16 at 9:15













                        • Also, you have to check that Name is not null, you can do it by doing: SELECT @names = @names + ISNULL(' ' + Name, '')

                          – Vita1ij
                          Mar 18 '16 at 10:49














                        27












                        27








                        27







                        I don't have access to a SQL Server at home, so I'm guess at the syntax here, but it's more or less:



                        DECLARE @names VARCHAR(500)

                        SELECT @names = @names + ' ' + Name
                        FROM Names





                        share|improve this answer













                        I don't have access to a SQL Server at home, so I'm guess at the syntax here, but it's more or less:



                        DECLARE @names VARCHAR(500)

                        SELECT @names = @names + ' ' + Name
                        FROM Names






                        share|improve this answer












                        share|improve this answer



                        share|improve this answer










                        answered Oct 12 '08 at 0:16









                        DanaDana

                        20k165370




                        20k165370








                        • 10





                          You'd need to init @names to something non-null, otherwise you will get NULL throughout; you'd also need to handle the delimiter (including the unnecessary one)

                          – Marc Gravell
                          Oct 12 '08 at 9:10






                        • 3





                          the only problem with this approach (which i use all the time) is that you can't embed it

                          – ekkis
                          Nov 23 '12 at 22:22











                        • To get rid of the leading space change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ' ' END + Name FROM Names

                          – Tian van Heerden
                          Mar 4 '16 at 9:15













                        • Also, you have to check that Name is not null, you can do it by doing: SELECT @names = @names + ISNULL(' ' + Name, '')

                          – Vita1ij
                          Mar 18 '16 at 10:49














                        • 10





                          You'd need to init @names to something non-null, otherwise you will get NULL throughout; you'd also need to handle the delimiter (including the unnecessary one)

                          – Marc Gravell
                          Oct 12 '08 at 9:10






                        • 3





                          the only problem with this approach (which i use all the time) is that you can't embed it

                          – ekkis
                          Nov 23 '12 at 22:22











                        • To get rid of the leading space change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ' ' END + Name FROM Names

                          – Tian van Heerden
                          Mar 4 '16 at 9:15













                        • Also, you have to check that Name is not null, you can do it by doing: SELECT @names = @names + ISNULL(' ' + Name, '')

                          – Vita1ij
                          Mar 18 '16 at 10:49








                        10




                        10





                        You'd need to init @names to something non-null, otherwise you will get NULL throughout; you'd also need to handle the delimiter (including the unnecessary one)

                        – Marc Gravell
                        Oct 12 '08 at 9:10





                        You'd need to init @names to something non-null, otherwise you will get NULL throughout; you'd also need to handle the delimiter (including the unnecessary one)

                        – Marc Gravell
                        Oct 12 '08 at 9:10




                        3




                        3





                        the only problem with this approach (which i use all the time) is that you can't embed it

                        – ekkis
                        Nov 23 '12 at 22:22





                        the only problem with this approach (which i use all the time) is that you can't embed it

                        – ekkis
                        Nov 23 '12 at 22:22













                        To get rid of the leading space change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ' ' END + Name FROM Names

                        – Tian van Heerden
                        Mar 4 '16 at 9:15







                        To get rid of the leading space change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ' ' END + Name FROM Names

                        – Tian van Heerden
                        Mar 4 '16 at 9:15















                        Also, you have to check that Name is not null, you can do it by doing: SELECT @names = @names + ISNULL(' ' + Name, '')

                        – Vita1ij
                        Mar 18 '16 at 10:49





                        Also, you have to check that Name is not null, you can do it by doing: SELECT @names = @names + ISNULL(' ' + Name, '')

                        – Vita1ij
                        Mar 18 '16 at 10:49











                        25














                        A recursive CTE solution was suggested, but no code provided. The code below is an example of a recursive CTE -- note that although the results match the question, the data doesn't quite match the given description, as I assume that you really want to be doing this on groups of rows, not all rows in the table. Changing it to match all rows in the table is left as an exercise for the reader.



                        ;with basetable as 
                        ( SELECT id, CAST(name as varchar(max))name,
                        ROW_NUMBER() OVER(Partition By id order by seq) rw,
                        COUNT(*) OVER (Partition By id) recs
                        FROM (VALUES (1, 'Johnny', 1), (1,'M', 2),
                        (2,'Bill', 1), (2, 'S.', 4), (2, 'Preston', 5), (2, 'Esq.', 6),
                        (3, 'Ted', 1), (3,'Theodore', 2), (3,'Logan', 3),
                        (4, 'Peter', 1), (4,'Paul', 2), (4,'Mary', 3)

                        )g(id, name, seq)
                        ),
                        rCTE as (
                        SELECT recs, id, name, rw from basetable where rw=1
                        UNION ALL
                        SELECT b.recs, r.ID, r.name +', '+ b.name name, r.rw+1
                        FROM basetable b
                        inner join rCTE r
                        on b.id = r.id and b.rw = r.rw+1
                        )
                        SELECT name FROM rCTE
                        WHERE recs = rw and ID=4





                        share|improve this answer
























                        • For the flabbergasted: this query inserts 12 rows (a 3 columns) into a temporary basetable, then creates a recursive Common Table Expression (rCTE) and then flattens the name column into a comma-separated string for 4 groups of ids. At first glance, I think this is more work than what most other solutions for SQL Server do.

                          – knb
                          Jul 24 '17 at 13:34








                        • 1





                          @knb: not sure if that is praise,condemnation,or just surprise. The base table is because I like my examples to actually work, it doesn't really have anything to do with the question.

                          – jmoreno
                          Jul 25 '17 at 2:20
















                        25














                        A recursive CTE solution was suggested, but no code provided. The code below is an example of a recursive CTE -- note that although the results match the question, the data doesn't quite match the given description, as I assume that you really want to be doing this on groups of rows, not all rows in the table. Changing it to match all rows in the table is left as an exercise for the reader.



                        ;with basetable as 
                        ( SELECT id, CAST(name as varchar(max))name,
                        ROW_NUMBER() OVER(Partition By id order by seq) rw,
                        COUNT(*) OVER (Partition By id) recs
                        FROM (VALUES (1, 'Johnny', 1), (1,'M', 2),
                        (2,'Bill', 1), (2, 'S.', 4), (2, 'Preston', 5), (2, 'Esq.', 6),
                        (3, 'Ted', 1), (3,'Theodore', 2), (3,'Logan', 3),
                        (4, 'Peter', 1), (4,'Paul', 2), (4,'Mary', 3)

                        )g(id, name, seq)
                        ),
                        rCTE as (
                        SELECT recs, id, name, rw from basetable where rw=1
                        UNION ALL
                        SELECT b.recs, r.ID, r.name +', '+ b.name name, r.rw+1
                        FROM basetable b
                        inner join rCTE r
                        on b.id = r.id and b.rw = r.rw+1
                        )
                        SELECT name FROM rCTE
                        WHERE recs = rw and ID=4





                        share|improve this answer
























                        • For the flabbergasted: this query inserts 12 rows (a 3 columns) into a temporary basetable, then creates a recursive Common Table Expression (rCTE) and then flattens the name column into a comma-separated string for 4 groups of ids. At first glance, I think this is more work than what most other solutions for SQL Server do.

                          – knb
                          Jul 24 '17 at 13:34








                        • 1





                          @knb: not sure if that is praise,condemnation,or just surprise. The base table is because I like my examples to actually work, it doesn't really have anything to do with the question.

                          – jmoreno
                          Jul 25 '17 at 2:20














                        25












                        25








                        25







                        A recursive CTE solution was suggested, but no code provided. The code below is an example of a recursive CTE -- note that although the results match the question, the data doesn't quite match the given description, as I assume that you really want to be doing this on groups of rows, not all rows in the table. Changing it to match all rows in the table is left as an exercise for the reader.



                        ;with basetable as 
                        ( SELECT id, CAST(name as varchar(max))name,
                        ROW_NUMBER() OVER(Partition By id order by seq) rw,
                        COUNT(*) OVER (Partition By id) recs
                        FROM (VALUES (1, 'Johnny', 1), (1,'M', 2),
                        (2,'Bill', 1), (2, 'S.', 4), (2, 'Preston', 5), (2, 'Esq.', 6),
                        (3, 'Ted', 1), (3,'Theodore', 2), (3,'Logan', 3),
                        (4, 'Peter', 1), (4,'Paul', 2), (4,'Mary', 3)

                        )g(id, name, seq)
                        ),
                        rCTE as (
                        SELECT recs, id, name, rw from basetable where rw=1
                        UNION ALL
                        SELECT b.recs, r.ID, r.name +', '+ b.name name, r.rw+1
                        FROM basetable b
                        inner join rCTE r
                        on b.id = r.id and b.rw = r.rw+1
                        )
                        SELECT name FROM rCTE
                        WHERE recs = rw and ID=4





                        share|improve this answer













                        A recursive CTE solution was suggested, but no code provided. The code below is an example of a recursive CTE -- note that although the results match the question, the data doesn't quite match the given description, as I assume that you really want to be doing this on groups of rows, not all rows in the table. Changing it to match all rows in the table is left as an exercise for the reader.



                        ;with basetable as 
                        ( SELECT id, CAST(name as varchar(max))name,
                        ROW_NUMBER() OVER(Partition By id order by seq) rw,
                        COUNT(*) OVER (Partition By id) recs
                        FROM (VALUES (1, 'Johnny', 1), (1,'M', 2),
                        (2,'Bill', 1), (2, 'S.', 4), (2, 'Preston', 5), (2, 'Esq.', 6),
                        (3, 'Ted', 1), (3,'Theodore', 2), (3,'Logan', 3),
                        (4, 'Peter', 1), (4,'Paul', 2), (4,'Mary', 3)

                        )g(id, name, seq)
                        ),
                        rCTE as (
                        SELECT recs, id, name, rw from basetable where rw=1
                        UNION ALL
                        SELECT b.recs, r.ID, r.name +', '+ b.name name, r.rw+1
                        FROM basetable b
                        inner join rCTE r
                        on b.id = r.id and b.rw = r.rw+1
                        )
                        SELECT name FROM rCTE
                        WHERE recs = rw and ID=4






                        share|improve this answer












                        share|improve this answer



                        share|improve this answer










                        answered Aug 9 '12 at 21:06









                        jmorenojmoreno

                        11.2k23866




                        11.2k23866













                        • For the flabbergasted: this query inserts 12 rows (a 3 columns) into a temporary basetable, then creates a recursive Common Table Expression (rCTE) and then flattens the name column into a comma-separated string for 4 groups of ids. At first glance, I think this is more work than what most other solutions for SQL Server do.

                          – knb
                          Jul 24 '17 at 13:34








                        • 1





                          @knb: not sure if that is praise,condemnation,or just surprise. The base table is because I like my examples to actually work, it doesn't really have anything to do with the question.

                          – jmoreno
                          Jul 25 '17 at 2:20



















                        • For the flabbergasted: this query inserts 12 rows (a 3 columns) into a temporary basetable, then creates a recursive Common Table Expression (rCTE) and then flattens the name column into a comma-separated string for 4 groups of ids. At first glance, I think this is more work than what most other solutions for SQL Server do.

                          – knb
                          Jul 24 '17 at 13:34








                        • 1





                          @knb: not sure if that is praise,condemnation,or just surprise. The base table is because I like my examples to actually work, it doesn't really have anything to do with the question.

                          – jmoreno
                          Jul 25 '17 at 2:20

















                        For the flabbergasted: this query inserts 12 rows (a 3 columns) into a temporary basetable, then creates a recursive Common Table Expression (rCTE) and then flattens the name column into a comma-separated string for 4 groups of ids. At first glance, I think this is more work than what most other solutions for SQL Server do.

                        – knb
                        Jul 24 '17 at 13:34







                        For the flabbergasted: this query inserts 12 rows (a 3 columns) into a temporary basetable, then creates a recursive Common Table Expression (rCTE) and then flattens the name column into a comma-separated string for 4 groups of ids. At first glance, I think this is more work than what most other solutions for SQL Server do.

                        – knb
                        Jul 24 '17 at 13:34






                        1




                        1





                        @knb: not sure if that is praise,condemnation,or just surprise. The base table is because I like my examples to actually work, it doesn't really have anything to do with the question.

                        – jmoreno
                        Jul 25 '17 at 2:20





                        @knb: not sure if that is praise,condemnation,or just surprise. The base table is because I like my examples to actually work, it doesn't really have anything to do with the question.

                        – jmoreno
                        Jul 25 '17 at 2:20











                        23














                        Starting with PostgreSQL 9.0 this is quite simple:



                        select string_agg(name, ',') 
                        from names;


                        In versions before 9.0 array_agg() can be used as shown by hgmnz






                        share|improve this answer


























                        • To do this with columns that are not of type text, you need to add a type cast: SELECT string_agg(non_text_type::text, ',') FROM table

                          – Torben Kohlmeier
                          May 17 '13 at 12:05













                        • @TorbenKohlmeier: you only need that for non-character columns (e.g. integer, decimal). It works just fine for varchar or char

                          – a_horse_with_no_name
                          May 17 '13 at 12:11
















                        23














                        Starting with PostgreSQL 9.0 this is quite simple:



                        select string_agg(name, ',') 
                        from names;


                        In versions before 9.0 array_agg() can be used as shown by hgmnz






                        share|improve this answer


























                        • To do this with columns that are not of type text, you need to add a type cast: SELECT string_agg(non_text_type::text, ',') FROM table

                          – Torben Kohlmeier
                          May 17 '13 at 12:05













                        • @TorbenKohlmeier: you only need that for non-character columns (e.g. integer, decimal). It works just fine for varchar or char

                          – a_horse_with_no_name
                          May 17 '13 at 12:11














                        23












                        23








                        23







                        Starting with PostgreSQL 9.0 this is quite simple:



                        select string_agg(name, ',') 
                        from names;


                        In versions before 9.0 array_agg() can be used as shown by hgmnz






                        share|improve this answer















                        Starting with PostgreSQL 9.0 this is quite simple:



                        select string_agg(name, ',') 
                        from names;


                        In versions before 9.0 array_agg() can be used as shown by hgmnz







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Oct 20 '14 at 10:42

























                        answered Nov 16 '12 at 23:15









                        a_horse_with_no_namea_horse_with_no_name

                        307k46468567




                        307k46468567













                        • To do this with columns that are not of type text, you need to add a type cast: SELECT string_agg(non_text_type::text, ',') FROM table

                          – Torben Kohlmeier
                          May 17 '13 at 12:05













                        • @TorbenKohlmeier: you only need that for non-character columns (e.g. integer, decimal). It works just fine for varchar or char

                          – a_horse_with_no_name
                          May 17 '13 at 12:11



















                        • To do this with columns that are not of type text, you need to add a type cast: SELECT string_agg(non_text_type::text, ',') FROM table

                          – Torben Kohlmeier
                          May 17 '13 at 12:05













                        • @TorbenKohlmeier: you only need that for non-character columns (e.g. integer, decimal). It works just fine for varchar or char

                          – a_horse_with_no_name
                          May 17 '13 at 12:11

















                        To do this with columns that are not of type text, you need to add a type cast: SELECT string_agg(non_text_type::text, ',') FROM table

                        – Torben Kohlmeier
                        May 17 '13 at 12:05







                        To do this with columns that are not of type text, you need to add a type cast: SELECT string_agg(non_text_type::text, ',') FROM table

                        – Torben Kohlmeier
                        May 17 '13 at 12:05















                        @TorbenKohlmeier: you only need that for non-character columns (e.g. integer, decimal). It works just fine for varchar or char

                        – a_horse_with_no_name
                        May 17 '13 at 12:11





                        @TorbenKohlmeier: you only need that for non-character columns (e.g. integer, decimal). It works just fine for varchar or char

                        – a_horse_with_no_name
                        May 17 '13 at 12:11











                        23














                        You need to create a variable that will hold your final result and select into it, like so.



                        Easiest Solution



                        DECLARE @char VARCHAR(MAX);

                        SELECT @char = COALESCE(@char + ', ' + [column], [column])
                        FROM [table];

                        PRINT @char;





                        share|improve this answer




























                          23














                          You need to create a variable that will hold your final result and select into it, like so.



                          Easiest Solution



                          DECLARE @char VARCHAR(MAX);

                          SELECT @char = COALESCE(@char + ', ' + [column], [column])
                          FROM [table];

                          PRINT @char;





                          share|improve this answer


























                            23












                            23








                            23







                            You need to create a variable that will hold your final result and select into it, like so.



                            Easiest Solution



                            DECLARE @char VARCHAR(MAX);

                            SELECT @char = COALESCE(@char + ', ' + [column], [column])
                            FROM [table];

                            PRINT @char;





                            share|improve this answer













                            You need to create a variable that will hold your final result and select into it, like so.



                            Easiest Solution



                            DECLARE @char VARCHAR(MAX);

                            SELECT @char = COALESCE(@char + ', ' + [column], [column])
                            FROM [table];

                            PRINT @char;






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Nov 15 '16 at 21:07









                            Tigerjz32Tigerjz32

                            2,59121731




                            2,59121731























                                21














                                In SQL Server vNext this will be built in with the STRING_AGG function, read more about it here:
                                https://msdn.microsoft.com/en-us/library/mt790580.aspx






                                share|improve this answer






























                                  21














                                  In SQL Server vNext this will be built in with the STRING_AGG function, read more about it here:
                                  https://msdn.microsoft.com/en-us/library/mt790580.aspx






                                  share|improve this answer




























                                    21












                                    21








                                    21







                                    In SQL Server vNext this will be built in with the STRING_AGG function, read more about it here:
                                    https://msdn.microsoft.com/en-us/library/mt790580.aspx






                                    share|improve this answer















                                    In SQL Server vNext this will be built in with the STRING_AGG function, read more about it here:
                                    https://msdn.microsoft.com/en-us/library/mt790580.aspx







                                    share|improve this answer














                                    share|improve this answer



                                    share|improve this answer








                                    edited Jan 10 '17 at 15:42

























                                    answered Nov 21 '16 at 11:27









                                    Henrik FransasHenrik Fransas

                                    905913




                                    905913























                                        17














                                        Using XML helped me in getting rows separated with commas. For the extra comma we can use the replace function of SQL Server. Instead of adding a comma, use of the AS 'data()' will concatenate the rows with spaces, which later can be replaced with commas as the syntax written below.



                                        REPLACE(
                                        (select FName AS 'data()' from NameList for xml path(''))
                                        , ' ', ', ')





                                        share|improve this answer





















                                        • 2





                                          This is the best answer here in my opinon. The use of declare variable is no good when you need to join in another table, and this is nice and short. Good work.

                                          – David Roussel
                                          Jun 2 '11 at 16:22






                                        • 7





                                          that's not working good if FName data has spaces already, for example "My Name"

                                          – binball
                                          Jun 8 '11 at 15:16













                                        • Really it is working for me on ms-sql 2016 Select REPLACE( (select Name AS 'data()' from Brand Where Id IN (1,2,3,4) for xml path('')) , ' ', ', ') as allBrands

                                          – Rejwanul Reja
                                          Apr 28 '17 at 10:13
















                                        17














                                        Using XML helped me in getting rows separated with commas. For the extra comma we can use the replace function of SQL Server. Instead of adding a comma, use of the AS 'data()' will concatenate the rows with spaces, which later can be replaced with commas as the syntax written below.



                                        REPLACE(
                                        (select FName AS 'data()' from NameList for xml path(''))
                                        , ' ', ', ')





                                        share|improve this answer





















                                        • 2





                                          This is the best answer here in my opinon. The use of declare variable is no good when you need to join in another table, and this is nice and short. Good work.

                                          – David Roussel
                                          Jun 2 '11 at 16:22






                                        • 7





                                          that's not working good if FName data has spaces already, for example "My Name"

                                          – binball
                                          Jun 8 '11 at 15:16













                                        • Really it is working for me on ms-sql 2016 Select REPLACE( (select Name AS 'data()' from Brand Where Id IN (1,2,3,4) for xml path('')) , ' ', ', ') as allBrands

                                          – Rejwanul Reja
                                          Apr 28 '17 at 10:13














                                        17












                                        17








                                        17







                                        Using XML helped me in getting rows separated with commas. For the extra comma we can use the replace function of SQL Server. Instead of adding a comma, use of the AS 'data()' will concatenate the rows with spaces, which later can be replaced with commas as the syntax written below.



                                        REPLACE(
                                        (select FName AS 'data()' from NameList for xml path(''))
                                        , ' ', ', ')





                                        share|improve this answer















                                        Using XML helped me in getting rows separated with commas. For the extra comma we can use the replace function of SQL Server. Instead of adding a comma, use of the AS 'data()' will concatenate the rows with spaces, which later can be replaced with commas as the syntax written below.



                                        REPLACE(
                                        (select FName AS 'data()' from NameList for xml path(''))
                                        , ' ', ', ')






                                        share|improve this answer














                                        share|improve this answer



                                        share|improve this answer








                                        edited Feb 26 '12 at 18:42









                                        Peter Mortensen

                                        13.9k1987113




                                        13.9k1987113










                                        answered Apr 7 '11 at 11:16









                                        DiwakarDiwakar

                                        17912




                                        17912








                                        • 2





                                          This is the best answer here in my opinon. The use of declare variable is no good when you need to join in another table, and this is nice and short. Good work.

                                          – David Roussel
                                          Jun 2 '11 at 16:22






                                        • 7





                                          that's not working good if FName data has spaces already, for example "My Name"

                                          – binball
                                          Jun 8 '11 at 15:16













                                        • Really it is working for me on ms-sql 2016 Select REPLACE( (select Name AS 'data()' from Brand Where Id IN (1,2,3,4) for xml path('')) , ' ', ', ') as allBrands

                                          – Rejwanul Reja
                                          Apr 28 '17 at 10:13














                                        • 2





                                          This is the best answer here in my opinon. The use of declare variable is no good when you need to join in another table, and this is nice and short. Good work.

                                          – David Roussel
                                          Jun 2 '11 at 16:22






                                        • 7





                                          that's not working good if FName data has spaces already, for example "My Name"

                                          – binball
                                          Jun 8 '11 at 15:16













                                        • Really it is working for me on ms-sql 2016 Select REPLACE( (select Name AS 'data()' from Brand Where Id IN (1,2,3,4) for xml path('')) , ' ', ', ') as allBrands

                                          – Rejwanul Reja
                                          Apr 28 '17 at 10:13








                                        2




                                        2





                                        This is the best answer here in my opinon. The use of declare variable is no good when you need to join in another table, and this is nice and short. Good work.

                                        – David Roussel
                                        Jun 2 '11 at 16:22





                                        This is the best answer here in my opinon. The use of declare variable is no good when you need to join in another table, and this is nice and short. Good work.

                                        – David Roussel
                                        Jun 2 '11 at 16:22




                                        7




                                        7





                                        that's not working good if FName data has spaces already, for example "My Name"

                                        – binball
                                        Jun 8 '11 at 15:16







                                        that's not working good if FName data has spaces already, for example "My Name"

                                        – binball
                                        Jun 8 '11 at 15:16















                                        Really it is working for me on ms-sql 2016 Select REPLACE( (select Name AS 'data()' from Brand Where Id IN (1,2,3,4) for xml path('')) , ' ', ', ') as allBrands

                                        – Rejwanul Reja
                                        Apr 28 '17 at 10:13





                                        Really it is working for me on ms-sql 2016 Select REPLACE( (select Name AS 'data()' from Brand Where Id IN (1,2,3,4) for xml path('')) , ' ', ', ') as allBrands

                                        – Rejwanul Reja
                                        Apr 28 '17 at 10:13











                                        17














                                        A ready-to-use solution, with no extra commas:



                                        select substring(
                                        (select ', '+Name AS 'data()' from Names for xml path(''))
                                        ,3, 255) as "MyList"


                                        An empty list will result in NULL value.
                                        Usually you will insert the list into a table column or program variable: adjust the 255 max length to your need.



                                        (Diwakar and Jens Frandsen provided good answers, but need improvement.)






                                        share|improve this answer


























                                        • There is a space before the comma when using this :(

                                          – slayernoah
                                          Nov 18 '15 at 18:23








                                        • 1





                                          Just replace ', ' with ',' if you don't want the extra space.

                                          – Daniel Reis
                                          Nov 18 '15 at 23:17
















                                        17














                                        A ready-to-use solution, with no extra commas:



                                        select substring(
                                        (select ', '+Name AS 'data()' from Names for xml path(''))
                                        ,3, 255) as "MyList"


                                        An empty list will result in NULL value.
                                        Usually you will insert the list into a table column or program variable: adjust the 255 max length to your need.



                                        (Diwakar and Jens Frandsen provided good answers, but need improvement.)






                                        share|improve this answer


























                                        • There is a space before the comma when using this :(

                                          – slayernoah
                                          Nov 18 '15 at 18:23








                                        • 1





                                          Just replace ', ' with ',' if you don't want the extra space.

                                          – Daniel Reis
                                          Nov 18 '15 at 23:17














                                        17












                                        17








                                        17







                                        A ready-to-use solution, with no extra commas:



                                        select substring(
                                        (select ', '+Name AS 'data()' from Names for xml path(''))
                                        ,3, 255) as "MyList"


                                        An empty list will result in NULL value.
                                        Usually you will insert the list into a table column or program variable: adjust the 255 max length to your need.



                                        (Diwakar and Jens Frandsen provided good answers, but need improvement.)






                                        share|improve this answer















                                        A ready-to-use solution, with no extra commas:



                                        select substring(
                                        (select ', '+Name AS 'data()' from Names for xml path(''))
                                        ,3, 255) as "MyList"


                                        An empty list will result in NULL value.
                                        Usually you will insert the list into a table column or program variable: adjust the 255 max length to your need.



                                        (Diwakar and Jens Frandsen provided good answers, but need improvement.)







                                        share|improve this answer














                                        share|improve this answer



                                        share|improve this answer








                                        edited Feb 26 '12 at 20:03









                                        Peter Mortensen

                                        13.9k1987113




                                        13.9k1987113










                                        answered Feb 3 '12 at 10:39









                                        Daniel ReisDaniel Reis

                                        9,91453565




                                        9,91453565













                                        • There is a space before the comma when using this :(

                                          – slayernoah
                                          Nov 18 '15 at 18:23








                                        • 1





                                          Just replace ', ' with ',' if you don't want the extra space.

                                          – Daniel Reis
                                          Nov 18 '15 at 23:17



















                                        • There is a space before the comma when using this :(

                                          – slayernoah
                                          Nov 18 '15 at 18:23








                                        • 1





                                          Just replace ', ' with ',' if you don't want the extra space.

                                          – Daniel Reis
                                          Nov 18 '15 at 23:17

















                                        There is a space before the comma when using this :(

                                        – slayernoah
                                        Nov 18 '15 at 18:23







                                        There is a space before the comma when using this :(

                                        – slayernoah
                                        Nov 18 '15 at 18:23






                                        1




                                        1





                                        Just replace ', ' with ',' if you don't want the extra space.

                                        – Daniel Reis
                                        Nov 18 '15 at 23:17





                                        Just replace ', ' with ',' if you don't want the extra space.

                                        – Daniel Reis
                                        Nov 18 '15 at 23:17











                                        11














                                        SELECT STUFF((SELECT ', ' + name FROM [table] FOR XML PATH('')), 1, 2, '')


                                        Here's a sample:



                                        DECLARE @t TABLE (name VARCHAR(10))
                                        INSERT INTO @t VALUES ('Peter'), ('Paul'), ('Mary')
                                        SELECT STUFF((SELECT ', ' + name FROM @t FOR XML PATH('')), 1, 2, '')
                                        --Peter, Paul, Mary





                                        share|improve this answer


























                                        • Thanks so much for giving the smallest possible solution, along with a working example! I had no idea why the top-voted answer works, nor how to replicate it.

                                          – jpaugh
                                          Mar 19 '18 at 14:21


















                                        11














                                        SELECT STUFF((SELECT ', ' + name FROM [table] FOR XML PATH('')), 1, 2, '')


                                        Here's a sample:



                                        DECLARE @t TABLE (name VARCHAR(10))
                                        INSERT INTO @t VALUES ('Peter'), ('Paul'), ('Mary')
                                        SELECT STUFF((SELECT ', ' + name FROM @t FOR XML PATH('')), 1, 2, '')
                                        --Peter, Paul, Mary





                                        share|improve this answer


























                                        • Thanks so much for giving the smallest possible solution, along with a working example! I had no idea why the top-voted answer works, nor how to replicate it.

                                          – jpaugh
                                          Mar 19 '18 at 14:21
















                                        11












                                        11








                                        11







                                        SELECT STUFF((SELECT ', ' + name FROM [table] FOR XML PATH('')), 1, 2, '')


                                        Here's a sample:



                                        DECLARE @t TABLE (name VARCHAR(10))
                                        INSERT INTO @t VALUES ('Peter'), ('Paul'), ('Mary')
                                        SELECT STUFF((SELECT ', ' + name FROM @t FOR XML PATH('')), 1, 2, '')
                                        --Peter, Paul, Mary





                                        share|improve this answer















                                        SELECT STUFF((SELECT ', ' + name FROM [table] FOR XML PATH('')), 1, 2, '')


                                        Here's a sample:



                                        DECLARE @t TABLE (name VARCHAR(10))
                                        INSERT INTO @t VALUES ('Peter'), ('Paul'), ('Mary')
                                        SELECT STUFF((SELECT ', ' + name FROM @t FOR XML PATH('')), 1, 2, '')
                                        --Peter, Paul, Mary






                                        share|improve this answer














                                        share|improve this answer



                                        share|improve this answer








                                        edited Feb 28 '18 at 16:04

























                                        answered Jan 25 '18 at 4:55









                                        Max SzczurekMax Szczurek

                                        3,25521325




                                        3,25521325













                                        • Thanks so much for giving the smallest possible solution, along with a working example! I had no idea why the top-voted answer works, nor how to replicate it.

                                          – jpaugh
                                          Mar 19 '18 at 14:21





















                                        • Thanks so much for giving the smallest possible solution, along with a working example! I had no idea why the top-voted answer works, nor how to replicate it.

                                          – jpaugh
                                          Mar 19 '18 at 14:21



















                                        Thanks so much for giving the smallest possible solution, along with a working example! I had no idea why the top-voted answer works, nor how to replicate it.

                                        – jpaugh
                                        Mar 19 '18 at 14:21







                                        Thanks so much for giving the smallest possible solution, along with a working example! I had no idea why the top-voted answer works, nor how to replicate it.

                                        – jpaugh
                                        Mar 19 '18 at 14:21













                                        10














                                        DECLARE @Names VARCHAR(8000)
                                        SELECT @name = ''
                                        SELECT @Names = @Names + ',' + Names FROM People
                                        SELECT SUBSTRING(2, @Names, 7998)


                                        This puts the stray comma at the beginning.



                                        However, if you need other columns, or to CSV a child table you need to wrap this in a scalar user defined field (UDF).



                                        You can use XML path as a correlated subquery in the SELECT clause too (but I'd have to wait until I go back to work because Google doesn't do work stuff at home :-)






                                        share|improve this answer






























                                          10














                                          DECLARE @Names VARCHAR(8000)
                                          SELECT @name = ''
                                          SELECT @Names = @Names + ',' + Names FROM People
                                          SELECT SUBSTRING(2, @Names, 7998)


                                          This puts the stray comma at the beginning.



                                          However, if you need other columns, or to CSV a child table you need to wrap this in a scalar user defined field (UDF).



                                          You can use XML path as a correlated subquery in the SELECT clause too (but I'd have to wait until I go back to work because Google doesn't do work stuff at home :-)






                                          share|improve this answer




























                                            10












                                            10








                                            10







                                            DECLARE @Names VARCHAR(8000)
                                            SELECT @name = ''
                                            SELECT @Names = @Names + ',' + Names FROM People
                                            SELECT SUBSTRING(2, @Names, 7998)


                                            This puts the stray comma at the beginning.



                                            However, if you need other columns, or to CSV a child table you need to wrap this in a scalar user defined field (UDF).



                                            You can use XML path as a correlated subquery in the SELECT clause too (but I'd have to wait until I go back to work because Google doesn't do work stuff at home :-)






                                            share|improve this answer















                                            DECLARE @Names VARCHAR(8000)
                                            SELECT @name = ''
                                            SELECT @Names = @Names + ',' + Names FROM People
                                            SELECT SUBSTRING(2, @Names, 7998)


                                            This puts the stray comma at the beginning.



                                            However, if you need other columns, or to CSV a child table you need to wrap this in a scalar user defined field (UDF).



                                            You can use XML path as a correlated subquery in the SELECT clause too (but I'd have to wait until I go back to work because Google doesn't do work stuff at home :-)







                                            share|improve this answer














                                            share|improve this answer



                                            share|improve this answer








                                            edited Feb 26 '12 at 18:39









                                            Peter Mortensen

                                            13.9k1987113




                                            13.9k1987113










                                            answered Oct 13 '08 at 17:24









                                            gbngbn

                                            347k58490581




                                            347k58490581























                                                9














                                                With the other answers, the person reading the answer must be aware of a specific domain table such as vehicle or student. The table must be created and populated with data to test a solution.



                                                Below is an example that uses SQL Server "Information_Schema.Columns" table. By using this solution, no tables need to be created or data added. This example creates a comma separated list of column names for all tables in the database.



                                                SELECT
                                                Table_Name
                                                ,STUFF((
                                                SELECT ',' + Column_Name
                                                FROM INFORMATION_SCHEMA.Columns Columns
                                                WHERE Tables.Table_Name = Columns.Table_Name
                                                ORDER BY Column_Name
                                                FOR XML PATH ('')), 1, 1, ''
                                                )Columns
                                                FROM INFORMATION_SCHEMA.Columns Tables
                                                GROUP BY TABLE_NAME





                                                share|improve this answer




























                                                  9














                                                  With the other answers, the person reading the answer must be aware of a specific domain table such as vehicle or student. The table must be created and populated with data to test a solution.



                                                  Below is an example that uses SQL Server "Information_Schema.Columns" table. By using this solution, no tables need to be created or data added. This example creates a comma separated list of column names for all tables in the database.



                                                  SELECT
                                                  Table_Name
                                                  ,STUFF((
                                                  SELECT ',' + Column_Name
                                                  FROM INFORMATION_SCHEMA.Columns Columns
                                                  WHERE Tables.Table_Name = Columns.Table_Name
                                                  ORDER BY Column_Name
                                                  FOR XML PATH ('')), 1, 1, ''
                                                  )Columns
                                                  FROM INFORMATION_SCHEMA.Columns Tables
                                                  GROUP BY TABLE_NAME





                                                  share|improve this answer


























                                                    9












                                                    9








                                                    9







                                                    With the other answers, the person reading the answer must be aware of a specific domain table such as vehicle or student. The table must be created and populated with data to test a solution.



                                                    Below is an example that uses SQL Server "Information_Schema.Columns" table. By using this solution, no tables need to be created or data added. This example creates a comma separated list of column names for all tables in the database.



                                                    SELECT
                                                    Table_Name
                                                    ,STUFF((
                                                    SELECT ',' + Column_Name
                                                    FROM INFORMATION_SCHEMA.Columns Columns
                                                    WHERE Tables.Table_Name = Columns.Table_Name
                                                    ORDER BY Column_Name
                                                    FOR XML PATH ('')), 1, 1, ''
                                                    )Columns
                                                    FROM INFORMATION_SCHEMA.Columns Tables
                                                    GROUP BY TABLE_NAME





                                                    share|improve this answer













                                                    With the other answers, the person reading the answer must be aware of a specific domain table such as vehicle or student. The table must be created and populated with data to test a solution.



                                                    Below is an example that uses SQL Server "Information_Schema.Columns" table. By using this solution, no tables need to be created or data added. This example creates a comma separated list of column names for all tables in the database.



                                                    SELECT
                                                    Table_Name
                                                    ,STUFF((
                                                    SELECT ',' + Column_Name
                                                    FROM INFORMATION_SCHEMA.Columns Columns
                                                    WHERE Tables.Table_Name = Columns.Table_Name
                                                    ORDER BY Column_Name
                                                    FOR XML PATH ('')), 1, 1, ''
                                                    )Columns
                                                    FROM INFORMATION_SCHEMA.Columns Tables
                                                    GROUP BY TABLE_NAME






                                                    share|improve this answer












                                                    share|improve this answer



                                                    share|improve this answer










                                                    answered May 4 '16 at 19:31









                                                    Mike Barlow - BarDevMike Barlow - BarDev

                                                    7,220155377




                                                    7,220155377























                                                        7














                                                        For Oracle DBs, see this question: How can multiple rows be concatenated into one in Oracle without creating a stored procedure?



                                                        The best answer appears to be by @Emmanuel, using the built-in LISTAGG() function, available in Oracle 11g Release 2 and later.



                                                        SELECT question_id,
                                                        LISTAGG(element_id, ',') WITHIN GROUP (ORDER BY element_id)
                                                        FROM YOUR_TABLE;
                                                        GROUP BY question_id


                                                        as @user762952 pointed out, and according to Oracle's documentation http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php, the WM_CONCAT() function is also an option. It seems stable, but Oracle explicitly recommends against using it for any application SQL, so use at your own risk.



                                                        Other than that, you will have to write your own function; the Oracle document above has a guide on how to do that.






                                                        share|improve this answer






























                                                          7














                                                          For Oracle DBs, see this question: How can multiple rows be concatenated into one in Oracle without creating a stored procedure?



                                                          The best answer appears to be by @Emmanuel, using the built-in LISTAGG() function, available in Oracle 11g Release 2 and later.



                                                          SELECT question_id,
                                                          LISTAGG(element_id, ',') WITHIN GROUP (ORDER BY element_id)
                                                          FROM YOUR_TABLE;
                                                          GROUP BY question_id


                                                          as @user762952 pointed out, and according to Oracle's documentation http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php, the WM_CONCAT() function is also an option. It seems stable, but Oracle explicitly recommends against using it for any application SQL, so use at your own risk.



                                                          Other than that, you will have to write your own function; the Oracle document above has a guide on how to do that.






                                                          share|improve this answer




























                                                            7












                                                            7








                                                            7







                                                            For Oracle DBs, see this question: How can multiple rows be concatenated into one in Oracle without creating a stored procedure?



                                                            The best answer appears to be by @Emmanuel, using the built-in LISTAGG() function, available in Oracle 11g Release 2 and later.



                                                            SELECT question_id,
                                                            LISTAGG(element_id, ',') WITHIN GROUP (ORDER BY element_id)
                                                            FROM YOUR_TABLE;
                                                            GROUP BY question_id


                                                            as @user762952 pointed out, and according to Oracle's documentation http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php, the WM_CONCAT() function is also an option. It seems stable, but Oracle explicitly recommends against using it for any application SQL, so use at your own risk.



                                                            Other than that, you will have to write your own function; the Oracle document above has a guide on how to do that.






                                                            share|improve this answer















                                                            For Oracle DBs, see this question: How can multiple rows be concatenated into one in Oracle without creating a stored procedure?



                                                            The best answer appears to be by @Emmanuel, using the built-in LISTAGG() function, available in Oracle 11g Release 2 and later.



                                                            SELECT question_id,
                                                            LISTAGG(element_id, ',') WITHIN GROUP (ORDER BY element_id)
                                                            FROM YOUR_TABLE;
                                                            GROUP BY question_id


                                                            as @user762952 pointed out, and according to Oracle's documentation http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php, the WM_CONCAT() function is also an option. It seems stable, but Oracle explicitly recommends against using it for any application SQL, so use at your own risk.



                                                            Other than that, you will have to write your own function; the Oracle document above has a guide on how to do that.







                                                            share|improve this answer














                                                            share|improve this answer



                                                            share|improve this answer








                                                            edited May 23 '17 at 11:47









                                                            Community

                                                            11




                                                            11










                                                            answered May 13 '13 at 16:02









                                                            ZeroKZeroK

                                                            36037




                                                            36037























                                                                7














                                                                I really liked elegancy of Dana's answer. Just wanted to make it complete.



                                                                DECLARE @names VARCHAR(MAX)
                                                                SET @names = ''

                                                                SELECT @names = @names + ', ' + Name FROM Names

                                                                -- Deleting last two symbols (', ')
                                                                SET @sSql = LEFT(@sSql, LEN(@sSql) - 1)





                                                                share|improve this answer


























                                                                • If you are deleting the last two symbols ', ', then you need to add ', ' after Name ('SELECT @names = @names + Name + ', ' FROM Names'). That way the last two chars will always be ', '.

                                                                  – Justin T
                                                                  Dec 18 '15 at 11:04













                                                                • In my case I needed to get rid of the leading comma so change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ', ' END + Name FROM Names then you don't have to truncate it afterwards.

                                                                  – Tian van Heerden
                                                                  Mar 4 '16 at 9:13
















                                                                7














                                                                I really liked elegancy of Dana's answer. Just wanted to make it complete.



                                                                DECLARE @names VARCHAR(MAX)
                                                                SET @names = ''

                                                                SELECT @names = @names + ', ' + Name FROM Names

                                                                -- Deleting last two symbols (', ')
                                                                SET @sSql = LEFT(@sSql, LEN(@sSql) - 1)





                                                                share|improve this answer


























                                                                • If you are deleting the last two symbols ', ', then you need to add ', ' after Name ('SELECT @names = @names + Name + ', ' FROM Names'). That way the last two chars will always be ', '.

                                                                  – Justin T
                                                                  Dec 18 '15 at 11:04













                                                                • In my case I needed to get rid of the leading comma so change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ', ' END + Name FROM Names then you don't have to truncate it afterwards.

                                                                  – Tian van Heerden
                                                                  Mar 4 '16 at 9:13














                                                                7












                                                                7








                                                                7







                                                                I really liked elegancy of Dana's answer. Just wanted to make it complete.



                                                                DECLARE @names VARCHAR(MAX)
                                                                SET @names = ''

                                                                SELECT @names = @names + ', ' + Name FROM Names

                                                                -- Deleting last two symbols (', ')
                                                                SET @sSql = LEFT(@sSql, LEN(@sSql) - 1)





                                                                share|improve this answer















                                                                I really liked elegancy of Dana's answer. Just wanted to make it complete.



                                                                DECLARE @names VARCHAR(MAX)
                                                                SET @names = ''

                                                                SELECT @names = @names + ', ' + Name FROM Names

                                                                -- Deleting last two symbols (', ')
                                                                SET @sSql = LEFT(@sSql, LEN(@sSql) - 1)






                                                                share|improve this answer














                                                                share|improve this answer



                                                                share|improve this answer








                                                                edited May 23 '17 at 11:55


























                                                                community wiki





                                                                3 revs, 2 users 92%
                                                                Oleg Sakharov














                                                                • If you are deleting the last two symbols ', ', then you need to add ', ' after Name ('SELECT @names = @names + Name + ', ' FROM Names'). That way the last two chars will always be ', '.

                                                                  – Justin T
                                                                  Dec 18 '15 at 11:04













                                                                • In my case I needed to get rid of the leading comma so change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ', ' END + Name FROM Names then you don't have to truncate it afterwards.

                                                                  – Tian van Heerden
                                                                  Mar 4 '16 at 9:13



















                                                                • If you are deleting the last two symbols ', ', then you need to add ', ' after Name ('SELECT @names = @names + Name + ', ' FROM Names'). That way the last two chars will always be ', '.

                                                                  – Justin T
                                                                  Dec 18 '15 at 11:04













                                                                • In my case I needed to get rid of the leading comma so change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ', ' END + Name FROM Names then you don't have to truncate it afterwards.

                                                                  – Tian van Heerden
                                                                  Mar 4 '16 at 9:13

















                                                                If you are deleting the last two symbols ', ', then you need to add ', ' after Name ('SELECT @names = @names + Name + ', ' FROM Names'). That way the last two chars will always be ', '.

                                                                – Justin T
                                                                Dec 18 '15 at 11:04







                                                                If you are deleting the last two symbols ', ', then you need to add ', ' after Name ('SELECT @names = @names + Name + ', ' FROM Names'). That way the last two chars will always be ', '.

                                                                – Justin T
                                                                Dec 18 '15 at 11:04















                                                                In my case I needed to get rid of the leading comma so change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ', ' END + Name FROM Names then you don't have to truncate it afterwards.

                                                                – Tian van Heerden
                                                                Mar 4 '16 at 9:13





                                                                In my case I needed to get rid of the leading comma so change the query to SELECT @names = @names + CASE WHEN LEN(@names)=0 THEN '' ELSE ', ' END + Name FROM Names then you don't have to truncate it afterwards.

                                                                – Tian van Heerden
                                                                Mar 4 '16 at 9:13











                                                                6














                                                                To avoid null values you can use CONCAT()



                                                                DECLARE @names VARCHAR(500)
                                                                SELECT @names = CONCAT(@names, ' ', name)
                                                                FROM Names
                                                                select @names





                                                                share|improve this answer
























                                                                • It would be nice to know why CONCAT works. A link to MSDN would be nice.

                                                                  – DaveBoltman
                                                                  Sep 20 '16 at 8:15
















                                                                6














                                                                To avoid null values you can use CONCAT()



                                                                DECLARE @names VARCHAR(500)
                                                                SELECT @names = CONCAT(@names, ' ', name)
                                                                FROM Names
                                                                select @names





                                                                share|improve this answer
























                                                                • It would be nice to know why CONCAT works. A link to MSDN would be nice.

                                                                  – DaveBoltman
                                                                  Sep 20 '16 at 8:15














                                                                6












                                                                6








                                                                6







                                                                To avoid null values you can use CONCAT()



                                                                DECLARE @names VARCHAR(500)
                                                                SELECT @names = CONCAT(@names, ' ', name)
                                                                FROM Names
                                                                select @names





                                                                share|improve this answer













                                                                To avoid null values you can use CONCAT()



                                                                DECLARE @names VARCHAR(500)
                                                                SELECT @names = CONCAT(@names, ' ', name)
                                                                FROM Names
                                                                select @names






                                                                share|improve this answer












                                                                share|improve this answer



                                                                share|improve this answer










                                                                answered Feb 12 '15 at 12:01









                                                                RapunzoRapunzo

                                                                62541840




                                                                62541840













                                                                • It would be nice to know why CONCAT works. A link to MSDN would be nice.

                                                                  – DaveBoltman
                                                                  Sep 20 '16 at 8:15



















                                                                • It would be nice to know why CONCAT works. A link to MSDN would be nice.

                                                                  – DaveBoltman
                                                                  Sep 20 '16 at 8:15

















                                                                It would be nice to know why CONCAT works. A link to MSDN would be nice.

                                                                – DaveBoltman
                                                                Sep 20 '16 at 8:15





                                                                It would be nice to know why CONCAT works. A link to MSDN would be nice.

                                                                – DaveBoltman
                                                                Sep 20 '16 at 8:15











                                                                6














                                                                This answer will require some privilege in server to work.



                                                                Assemblies are a good option for you. There are a lot of sites that explain how to create it. The one I think is very well explained is this one



                                                                If you want, I have already created the assembly, and it is possible to download the DLL here.



                                                                Once you have downloaded it, you will need to run the following script in your SQL Server:



                                                                CREATE Assembly concat_assembly 
                                                                AUTHORIZATION dbo
                                                                FROM '<PATH TO Concat.dll IN SERVER>'
                                                                WITH PERMISSION_SET = SAFE;
                                                                GO

                                                                CREATE AGGREGATE dbo.concat (

                                                                @Value NVARCHAR(MAX)
                                                                , @Delimiter NVARCHAR(4000)

                                                                ) RETURNS NVARCHAR(MAX)
                                                                EXTERNAL Name concat_assembly.[Concat.Concat];
                                                                GO

                                                                sp_configure 'clr enabled', 1;
                                                                RECONFIGURE


                                                                Observe that the path to assembly may be accessible to server. Since you have successfully done all the steps, you can use the function like:



                                                                SELECT dbo.Concat(field1, ',')
                                                                FROM Table1


                                                                Hope it helps!!!






                                                                share|improve this answer




























                                                                  6














                                                                  This answer will require some privilege in server to work.



                                                                  Assemblies are a good option for you. There are a lot of sites that explain how to create it. The one I think is very well explained is this one



                                                                  If you want, I have already created the assembly, and it is possible to download the DLL here.



                                                                  Once you have downloaded it, you will need to run the following script in your SQL Server:



                                                                  CREATE Assembly concat_assembly 
                                                                  AUTHORIZATION dbo
                                                                  FROM '<PATH TO Concat.dll IN SERVER>'
                                                                  WITH PERMISSION_SET = SAFE;
                                                                  GO

                                                                  CREATE AGGREGATE dbo.concat (

                                                                  @Value NVARCHAR(MAX)
                                                                  , @Delimiter NVARCHAR(4000)

                                                                  ) RETURNS NVARCHAR(MAX)
                                                                  EXTERNAL Name concat_assembly.[Concat.Concat];
                                                                  GO

                                                                  sp_configure 'clr enabled', 1;
                                                                  RECONFIGURE


                                                                  Observe that the path to assembly may be accessible to server. Since you have successfully done all the steps, you can use the function like:



                                                                  SELECT dbo.Concat(field1, ',')
                                                                  FROM Table1


                                                                  Hope it helps!!!






                                                                  share|improve this answer


























                                                                    6












                                                                    6








                                                                    6







                                                                    This answer will require some privilege in server to work.



                                                                    Assemblies are a good option for you. There are a lot of sites that explain how to create it. The one I think is very well explained is this one



                                                                    If you want, I have already created the assembly, and it is possible to download the DLL here.



                                                                    Once you have downloaded it, you will need to run the following script in your SQL Server:



                                                                    CREATE Assembly concat_assembly 
                                                                    AUTHORIZATION dbo
                                                                    FROM '<PATH TO Concat.dll IN SERVER>'
                                                                    WITH PERMISSION_SET = SAFE;
                                                                    GO

                                                                    CREATE AGGREGATE dbo.concat (

                                                                    @Value NVARCHAR(MAX)
                                                                    , @Delimiter NVARCHAR(4000)

                                                                    ) RETURNS NVARCHAR(MAX)
                                                                    EXTERNAL Name concat_assembly.[Concat.Concat];
                                                                    GO

                                                                    sp_configure 'clr enabled', 1;
                                                                    RECONFIGURE


                                                                    Observe that the path to assembly may be accessible to server. Since you have successfully done all the steps, you can use the function like:



                                                                    SELECT dbo.Concat(field1, ',')
                                                                    FROM Table1


                                                                    Hope it helps!!!






                                                                    share|improve this answer













                                                                    This answer will require some privilege in server to work.



                                                                    Assemblies are a good option for you. There are a lot of sites that explain how to create it. The one I think is very well explained is this one



                                                                    If you want, I have already created the assembly, and it is possible to download the DLL here.



                                                                    Once you have downloaded it, you will need to run the following script in your SQL Server:



                                                                    CREATE Assembly concat_assembly 
                                                                    AUTHORIZATION dbo
                                                                    FROM '<PATH TO Concat.dll IN SERVER>'
                                                                    WITH PERMISSION_SET = SAFE;
                                                                    GO

                                                                    CREATE AGGREGATE dbo.concat (

                                                                    @Value NVARCHAR(MAX)
                                                                    , @Delimiter NVARCHAR(4000)

                                                                    ) RETURNS NVARCHAR(MAX)
                                                                    EXTERNAL Name concat_assembly.[Concat.Concat];
                                                                    GO

                                                                    sp_configure 'clr enabled', 1;
                                                                    RECONFIGURE


                                                                    Observe that the path to assembly may be accessible to server. Since you have successfully done all the steps, you can use the function like:



                                                                    SELECT dbo.Concat(field1, ',')
                                                                    FROM Table1


                                                                    Hope it helps!!!







                                                                    share|improve this answer












                                                                    share|improve this answer



                                                                    share|improve this answer










                                                                    answered May 8 '15 at 1:39









                                                                    NizamNizam

                                                                    3,35333252




                                                                    3,35333252























                                                                        5














                                                                        I usually use select like this to concatenate strings in SQL Server:



                                                                        with lines as 
                                                                        (
                                                                        select
                                                                        row_number() over(order by id) id, -- id is a line id
                                                                        line -- line of text.
                                                                        from
                                                                        source -- line source
                                                                        ),
                                                                        result_lines as
                                                                        (
                                                                        select
                                                                        id,
                                                                        cast(line as nvarchar(max)) line
                                                                        from
                                                                        lines
                                                                        where
                                                                        id = 1
                                                                        union all
                                                                        select
                                                                        l.id,
                                                                        cast(r.line + N', ' + l.line as nvarchar(max))
                                                                        from
                                                                        lines l
                                                                        inner join
                                                                        result_lines r
                                                                        on
                                                                        l.id = r.id + 1
                                                                        )
                                                                        select top 1
                                                                        line
                                                                        from
                                                                        result_lines
                                                                        order by
                                                                        id desc





                                                                        share|improve this answer






























                                                                          5














                                                                          I usually use select like this to concatenate strings in SQL Server:



                                                                          with lines as 
                                                                          (
                                                                          select
                                                                          row_number() over(order by id) id, -- id is a line id
                                                                          line -- line of text.
                                                                          from
                                                                          source -- line source
                                                                          ),
                                                                          result_lines as
                                                                          (
                                                                          select
                                                                          id,
                                                                          cast(line as nvarchar(max)) line
                                                                          from
                                                                          lines
                                                                          where
                                                                          id = 1
                                                                          union all
                                                                          select
                                                                          l.id,
                                                                          cast(r.line + N', ' + l.line as nvarchar(max))
                                                                          from
                                                                          lines l
                                                                          inner join
                                                                          result_lines r
                                                                          on
                                                                          l.id = r.id + 1
                                                                          )
                                                                          select top 1
                                                                          line
                                                                          from
                                                                          result_lines
                                                                          order by
                                                                          id desc





                                                                          share|improve this answer




























                                                                            5












                                                                            5








                                                                            5







                                                                            I usually use select like this to concatenate strings in SQL Server:



                                                                            with lines as 
                                                                            (
                                                                            select
                                                                            row_number() over(order by id) id, -- id is a line id
                                                                            line -- line of text.
                                                                            from
                                                                            source -- line source
                                                                            ),
                                                                            result_lines as
                                                                            (
                                                                            select
                                                                            id,
                                                                            cast(line as nvarchar(max)) line
                                                                            from
                                                                            lines
                                                                            where
                                                                            id = 1
                                                                            union all
                                                                            select
                                                                            l.id,
                                                                            cast(r.line + N', ' + l.line as nvarchar(max))
                                                                            from
                                                                            lines l
                                                                            inner join
                                                                            result_lines r
                                                                            on
                                                                            l.id = r.id + 1
                                                                            )
                                                                            select top 1
                                                                            line
                                                                            from
                                                                            result_lines
                                                                            order by
                                                                            id desc





                                                                            share|improve this answer















                                                                            I usually use select like this to concatenate strings in SQL Server:



                                                                            with lines as 
                                                                            (
                                                                            select
                                                                            row_number() over(order by id) id, -- id is a line id
                                                                            line -- line of text.
                                                                            from
                                                                            source -- line source
                                                                            ),
                                                                            result_lines as
                                                                            (
                                                                            select
                                                                            id,
                                                                            cast(line as nvarchar(max)) line
                                                                            from
                                                                            lines
                                                                            where
                                                                            id = 1
                                                                            union all
                                                                            select
                                                                            l.id,
                                                                            cast(r.line + N', ' + l.line as nvarchar(max))
                                                                            from
                                                                            lines l
                                                                            inner join
                                                                            result_lines r
                                                                            on
                                                                            l.id = r.id + 1
                                                                            )
                                                                            select top 1
                                                                            line
                                                                            from
                                                                            result_lines
                                                                            order by
                                                                            id desc






                                                                            share|improve this answer














                                                                            share|improve this answer



                                                                            share|improve this answer








                                                                            edited Jul 6 '11 at 7:06

























                                                                            answered Jul 6 '11 at 6:58









                                                                            Vladimir NesterovskyVladimir Nesterovsky

                                                                            402511




                                                                            402511























                                                                                5














                                                                                If you want to deal with nulls you can do it by adding a where clause or add another COALESCE around the first one.



                                                                                DECLARE @Names VARCHAR(8000) 
                                                                                SELECT @Names = COALESCE(COALESCE(@Names + ', ', '') + Name, @Names) FROM People





                                                                                share|improve this answer




























                                                                                  5














                                                                                  If you want to deal with nulls you can do it by adding a where clause or add another COALESCE around the first one.



                                                                                  DECLARE @Names VARCHAR(8000) 
                                                                                  SELECT @Names = COALESCE(COALESCE(@Names + ', ', '') + Name, @Names) FROM People





                                                                                  share|improve this answer


























                                                                                    5












                                                                                    5








                                                                                    5







                                                                                    If you want to deal with nulls you can do it by adding a where clause or add another COALESCE around the first one.



                                                                                    DECLARE @Names VARCHAR(8000) 
                                                                                    SELECT @Names = COALESCE(COALESCE(@Names + ', ', '') + Name, @Names) FROM People





                                                                                    share|improve this answer













                                                                                    If you want to deal with nulls you can do it by adding a where clause or add another COALESCE around the first one.



                                                                                    DECLARE @Names VARCHAR(8000) 
                                                                                    SELECT @Names = COALESCE(COALESCE(@Names + ', ', '') + Name, @Names) FROM People






                                                                                    share|improve this answer












                                                                                    share|improve this answer



                                                                                    share|improve this answer










                                                                                    answered Jul 27 '11 at 20:05









                                                                                    PramodPramod

                                                                                    5913




                                                                                    5913























                                                                                        5














                                                                                        MySQL complete Example:



                                                                                        We have Users which can have many Data's and we want to have an output, where we can see all users Datas in a list:



                                                                                        Result:



                                                                                        ___________________________
                                                                                        | id | rowList |
                                                                                        |-------------------------|
                                                                                        | 0 | 6, 9 |
                                                                                        | 1 | 1,2,3,4,5,7,8,1 |
                                                                                        |_________________________|


                                                                                        Table Setup:



                                                                                        CREATE TABLE `Data` (
                                                                                        `id` int(11) NOT NULL,
                                                                                        `user_id` int(11) NOT NULL
                                                                                        ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;


                                                                                        INSERT INTO `Data` (`id`, `user_id`) VALUES
                                                                                        (1, 1),
                                                                                        (2, 1),
                                                                                        (3, 1),
                                                                                        (4, 1),
                                                                                        (5, 1),
                                                                                        (6, 0),
                                                                                        (7, 1),
                                                                                        (8, 1),
                                                                                        (9, 0),
                                                                                        (10, 1);


                                                                                        CREATE TABLE `User` (
                                                                                        `id` int(11) NOT NULL
                                                                                        ) ENGINE=InnoDB DEFAULT CHARSET=latin1;


                                                                                        INSERT INTO `User` (`id`) VALUES
                                                                                        (0),
                                                                                        (1);


                                                                                        Query:



                                                                                        SELECT User.id, GROUP_CONCAT(Data.id ORDER BY Data.id) AS rowList FROM User LEFT JOIN Data ON User.id = Data.user_id GROUP BY User.id





                                                                                        share|improve this answer




























                                                                                          5














                                                                                          MySQL complete Example:



                                                                                          We have Users which can have many Data's and we want to have an output, where we can see all users Datas in a list:



                                                                                          Result:



                                                                                          ___________________________
                                                                                          | id | rowList |
                                                                                          |-------------------------|
                                                                                          | 0 | 6, 9 |
                                                                                          | 1 | 1,2,3,4,5,7,8,1 |
                                                                                          |_________________________|


                                                                                          Table Setup:



                                                                                          CREATE TABLE `Data` (
                                                                                          `id` int(11) NOT NULL,
                                                                                          `user_id` int(11) NOT NULL
                                                                                          ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;


                                                                                          INSERT INTO `Data` (`id`, `user_id`) VALUES
                                                                                          (1, 1),
                                                                                          (2, 1),
                                                                                          (3, 1),
                                                                                          (4, 1),
                                                                                          (5, 1),
                                                                                          (6, 0),
                                                                                          (7, 1),
                                                                                          (8, 1),
                                                                                          (9, 0),
                                                                                          (10, 1);


                                                                                          CREATE TABLE `User` (
                                                                                          `id` int(11) NOT NULL
                                                                                          ) ENGINE=InnoDB DEFAULT CHARSET=latin1;


                                                                                          INSERT INTO `User` (`id`) VALUES
                                                                                          (0),
                                                                                          (1);


                                                                                          Query:



                                                                                          SELECT User.id, GROUP_CONCAT(Data.id ORDER BY Data.id) AS rowList FROM User LEFT JOIN Data ON User.id = Data.user_id GROUP BY User.id





                                                                                          share|improve this answer


























                                                                                            5












                                                                                            5








                                                                                            5







                                                                                            MySQL complete Example:



                                                                                            We have Users which can have many Data's and we want to have an output, where we can see all users Datas in a list:



                                                                                            Result:



                                                                                            ___________________________
                                                                                            | id | rowList |
                                                                                            |-------------------------|
                                                                                            | 0 | 6, 9 |
                                                                                            | 1 | 1,2,3,4,5,7,8,1 |
                                                                                            |_________________________|


                                                                                            Table Setup:



                                                                                            CREATE TABLE `Data` (
                                                                                            `id` int(11) NOT NULL,
                                                                                            `user_id` int(11) NOT NULL
                                                                                            ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;


                                                                                            INSERT INTO `Data` (`id`, `user_id`) VALUES
                                                                                            (1, 1),
                                                                                            (2, 1),
                                                                                            (3, 1),
                                                                                            (4, 1),
                                                                                            (5, 1),
                                                                                            (6, 0),
                                                                                            (7, 1),
                                                                                            (8, 1),
                                                                                            (9, 0),
                                                                                            (10, 1);


                                                                                            CREATE TABLE `User` (
                                                                                            `id` int(11) NOT NULL
                                                                                            ) ENGINE=InnoDB DEFAULT CHARSET=latin1;


                                                                                            INSERT INTO `User` (`id`) VALUES
                                                                                            (0),
                                                                                            (1);


                                                                                            Query:



                                                                                            SELECT User.id, GROUP_CONCAT(Data.id ORDER BY Data.id) AS rowList FROM User LEFT JOIN Data ON User.id = Data.user_id GROUP BY User.id





                                                                                            share|improve this answer













                                                                                            MySQL complete Example:



                                                                                            We have Users which can have many Data's and we want to have an output, where we can see all users Datas in a list:



                                                                                            Result:



                                                                                            ___________________________
                                                                                            | id | rowList |
                                                                                            |-------------------------|
                                                                                            | 0 | 6, 9 |
                                                                                            | 1 | 1,2,3,4,5,7,8,1 |
                                                                                            |_________________________|


                                                                                            Table Setup:



                                                                                            CREATE TABLE `Data` (
                                                                                            `id` int(11) NOT NULL,
                                                                                            `user_id` int(11) NOT NULL
                                                                                            ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;


                                                                                            INSERT INTO `Data` (`id`, `user_id`) VALUES
                                                                                            (1, 1),
                                                                                            (2, 1),
                                                                                            (3, 1),
                                                                                            (4, 1),
                                                                                            (5, 1),
                                                                                            (6, 0),
                                                                                            (7, 1),
                                                                                            (8, 1),
                                                                                            (9, 0),
                                                                                            (10, 1);


                                                                                            CREATE TABLE `User` (
                                                                                            `id` int(11) NOT NULL
                                                                                            ) ENGINE=InnoDB DEFAULT CHARSET=latin1;


                                                                                            INSERT INTO `User` (`id`) VALUES
                                                                                            (0),
                                                                                            (1);


                                                                                            Query:



                                                                                            SELECT User.id, GROUP_CONCAT(Data.id ORDER BY Data.id) AS rowList FROM User LEFT JOIN Data ON User.id = Data.user_id GROUP BY User.id






                                                                                            share|improve this answer












                                                                                            share|improve this answer



                                                                                            share|improve this answer










                                                                                            answered Jul 22 '15 at 7:51









                                                                                            user1767754user1767754

                                                                                            10.3k57485




                                                                                            10.3k57485























                                                                                                4














                                                                                                In Oracle, it is wm_concat. I believe this function is available in the 10g release and higher.






                                                                                                share|improve this answer






























                                                                                                  4














                                                                                                  In Oracle, it is wm_concat. I believe this function is available in the 10g release and higher.






                                                                                                  share|improve this answer




























                                                                                                    4












                                                                                                    4








                                                                                                    4







                                                                                                    In Oracle, it is wm_concat. I believe this function is available in the 10g release and higher.






                                                                                                    share|improve this answer















                                                                                                    In Oracle, it is wm_concat. I believe this function is available in the 10g release and higher.







                                                                                                    share|improve this answer














                                                                                                    share|improve this answer



                                                                                                    share|improve this answer








                                                                                                    edited Feb 26 '12 at 18:44









                                                                                                    Peter Mortensen

                                                                                                    13.9k1987113




                                                                                                    13.9k1987113










                                                                                                    answered Jun 3 '11 at 18:14









                                                                                                    user762952user762952

                                                                                                    491




                                                                                                    491























                                                                                                        4














                                                                                                        This can be useful too



                                                                                                        create table #test (id int,name varchar(10))
                                                                                                        --use separate inserts on older versions of SQL Server
                                                                                                        insert into #test values (1,'Peter'), (1,'Paul'), (1,'Mary'), (2,'Alex'), (3,'Jack')

                                                                                                        DECLARE @t VARCHAR(255)
                                                                                                        SELECT @t = ISNULL(@t + ',' + name, name) FROM #test WHERE id = 1
                                                                                                        select @t
                                                                                                        drop table #test


                                                                                                        returns



                                                                                                        Peter,Paul,Mary





                                                                                                        share|improve this answer



















                                                                                                        • 5





                                                                                                          Unfortunately this behavior seems not to be officially supported. MSDN says: "If a variable is referenced in a select list, it should be assigned a scalar value or the SELECT statement should only return one row." And there are people who observed problems: sqlmag.com/sql-server/multi-row-variable-assignment-and-order

                                                                                                          – blueling
                                                                                                          Dec 5 '13 at 9:11


















                                                                                                        4














                                                                                                        This can be useful too



                                                                                                        create table #test (id int,name varchar(10))
                                                                                                        --use separate inserts on older versions of SQL Server
                                                                                                        insert into #test values (1,'Peter'), (1,'Paul'), (1,'Mary'), (2,'Alex'), (3,'Jack')

                                                                                                        DECLARE @t VARCHAR(255)
                                                                                                        SELECT @t = ISNULL(@t + ',' + name, name) FROM #test WHERE id = 1
                                                                                                        select @t
                                                                                                        drop table #test


                                                                                                        returns



                                                                                                        Peter,Paul,Mary





                                                                                                        share|improve this answer



















                                                                                                        • 5





                                                                                                          Unfortunately this behavior seems not to be officially supported. MSDN says: "If a variable is referenced in a select list, it should be assigned a scalar value or the SELECT statement should only return one row." And there are people who observed problems: sqlmag.com/sql-server/multi-row-variable-assignment-and-order

                                                                                                          – blueling
                                                                                                          Dec 5 '13 at 9:11
















                                                                                                        4












                                                                                                        4








                                                                                                        4







                                                                                                        This can be useful too



                                                                                                        create table #test (id int,name varchar(10))
                                                                                                        --use separate inserts on older versions of SQL Server
                                                                                                        insert into #test values (1,'Peter'), (1,'Paul'), (1,'Mary'), (2,'Alex'), (3,'Jack')

                                                                                                        DECLARE @t VARCHAR(255)
                                                                                                        SELECT @t = ISNULL(@t + ',' + name, name) FROM #test WHERE id = 1
                                                                                                        select @t
                                                                                                        drop table #test


                                                                                                        returns



                                                                                                        Peter,Paul,Mary





                                                                                                        share|improve this answer













                                                                                                        This can be useful too



                                                                                                        create table #test (id int,name varchar(10))
                                                                                                        --use separate inserts on older versions of SQL Server
                                                                                                        insert into #test values (1,'Peter'), (1,'Paul'), (1,'Mary'), (2,'Alex'), (3,'Jack')

                                                                                                        DECLARE @t VARCHAR(255)
                                                                                                        SELECT @t = ISNULL(@t + ',' + name, name) FROM #test WHERE id = 1
                                                                                                        select @t
                                                                                                        drop table #test


                                                                                                        returns



                                                                                                        Peter,Paul,Mary






                                                                                                        share|improve this answer












                                                                                                        share|improve this answer



                                                                                                        share|improve this answer










                                                                                                        answered Oct 25 '13 at 8:14









                                                                                                        endo64endo64

                                                                                                        1,6051724




                                                                                                        1,6051724








                                                                                                        • 5





                                                                                                          Unfortunately this behavior seems not to be officially supported. MSDN says: "If a variable is referenced in a select list, it should be assigned a scalar value or the SELECT statement should only return one row." And there are people who observed problems: sqlmag.com/sql-server/multi-row-variable-assignment-and-order

                                                                                                          – blueling
                                                                                                          Dec 5 '13 at 9:11
















                                                                                                        • 5





                                                                                                          Unfortunately this behavior seems not to be officially supported. MSDN says: "If a variable is referenced in a select list, it should be assigned a scalar value or the SELECT statement should only return one row." And there are people who observed problems: sqlmag.com/sql-server/multi-row-variable-assignment-and-order

                                                                                                          – blueling
                                                                                                          Dec 5 '13 at 9:11










                                                                                                        5




                                                                                                        5





                                                                                                        Unfortunately this behavior seems not to be officially supported. MSDN says: "If a variable is referenced in a select list, it should be assigned a scalar value or the SELECT statement should only return one row." And there are people who observed problems: sqlmag.com/sql-server/multi-row-variable-assignment-and-order

                                                                                                        – blueling
                                                                                                        Dec 5 '13 at 9:11







                                                                                                        Unfortunately this behavior seems not to be officially supported. MSDN says: "If a variable is referenced in a select list, it should be assigned a scalar value or the SELECT statement should only return one row." And there are people who observed problems: sqlmag.com/sql-server/multi-row-variable-assignment-and-order

                                                                                                        – blueling
                                                                                                        Dec 5 '13 at 9:11













                                                                                                        3














                                                                                                        This method applies to Teradata Aster database only as it utilizes its NPATH function.



                                                                                                        Again, we have table Students



                                                                                                        SubjectID       StudentName
                                                                                                        ---------- -------------
                                                                                                        1 Mary
                                                                                                        1 John
                                                                                                        1 Sam
                                                                                                        2 Alaina
                                                                                                        2 Edward


                                                                                                        Then with NPATH it is just single SELECT:



                                                                                                        SELECT * FROM npath(
                                                                                                        ON Students
                                                                                                        PARTITION BY SubjectID
                                                                                                        ORDER BY StudentName
                                                                                                        MODE(nonoverlapping)
                                                                                                        PATTERN('A*')
                                                                                                        SYMBOLS(
                                                                                                        'true' as A
                                                                                                        )
                                                                                                        RESULT(
                                                                                                        FIRST(SubjectID of A) as SubjectID,
                                                                                                        ACCUMULATE(StudentName of A) as StudentName
                                                                                                        )
                                                                                                        );


                                                                                                        Result:



                                                                                                        SubjectID       StudentName
                                                                                                        ---------- -------------
                                                                                                        1 [John, Mary, Sam]
                                                                                                        2 [Alaina, Edward]





                                                                                                        share|improve this answer




























                                                                                                          3














                                                                                                          This method applies to Teradata Aster database only as it utilizes its NPATH function.



                                                                                                          Again, we have table Students



                                                                                                          SubjectID       StudentName
                                                                                                          ---------- -------------
                                                                                                          1 Mary
                                                                                                          1 John
                                                                                                          1 Sam
                                                                                                          2 Alaina
                                                                                                          2 Edward


                                                                                                          Then with NPATH it is just single SELECT:



                                                                                                          SELECT * FROM npath(
                                                                                                          ON Students
                                                                                                          PARTITION BY SubjectID
                                                                                                          ORDER BY StudentName
                                                                                                          MODE(nonoverlapping)
                                                                                                          PATTERN('A*')
                                                                                                          SYMBOLS(
                                                                                                          'true' as A
                                                                                                          )
                                                                                                          RESULT(
                                                                                                          FIRST(SubjectID of A) as SubjectID,
                                                                                                          ACCUMULATE(StudentName of A) as StudentName
                                                                                                          )
                                                                                                          );


                                                                                                          Result:



                                                                                                          SubjectID       StudentName
                                                                                                          ---------- -------------
                                                                                                          1 [John, Mary, Sam]
                                                                                                          2 [Alaina, Edward]





                                                                                                          share|improve this answer


























                                                                                                            3












                                                                                                            3








                                                                                                            3







                                                                                                            This method applies to Teradata Aster database only as it utilizes its NPATH function.



                                                                                                            Again, we have table Students



                                                                                                            SubjectID       StudentName
                                                                                                            ---------- -------------
                                                                                                            1 Mary
                                                                                                            1 John
                                                                                                            1 Sam
                                                                                                            2 Alaina
                                                                                                            2 Edward


                                                                                                            Then with NPATH it is just single SELECT:



                                                                                                            SELECT * FROM npath(
                                                                                                            ON Students
                                                                                                            PARTITION BY SubjectID
                                                                                                            ORDER BY StudentName
                                                                                                            MODE(nonoverlapping)
                                                                                                            PATTERN('A*')
                                                                                                            SYMBOLS(
                                                                                                            'true' as A
                                                                                                            )
                                                                                                            RESULT(
                                                                                                            FIRST(SubjectID of A) as SubjectID,
                                                                                                            ACCUMULATE(StudentName of A) as StudentName
                                                                                                            )
                                                                                                            );


                                                                                                            Result:



                                                                                                            SubjectID       StudentName
                                                                                                            ---------- -------------
                                                                                                            1 [John, Mary, Sam]
                                                                                                            2 [Alaina, Edward]





                                                                                                            share|improve this answer













                                                                                                            This method applies to Teradata Aster database only as it utilizes its NPATH function.



                                                                                                            Again, we have table Students



                                                                                                            SubjectID       StudentName
                                                                                                            ---------- -------------
                                                                                                            1 Mary
                                                                                                            1 John
                                                                                                            1 Sam
                                                                                                            2 Alaina
                                                                                                            2 Edward


                                                                                                            Then with NPATH it is just single SELECT:



                                                                                                            SELECT * FROM npath(
                                                                                                            ON Students
                                                                                                            PARTITION BY SubjectID
                                                                                                            ORDER BY StudentName
                                                                                                            MODE(nonoverlapping)
                                                                                                            PATTERN('A*')
                                                                                                            SYMBOLS(
                                                                                                            'true' as A
                                                                                                            )
                                                                                                            RESULT(
                                                                                                            FIRST(SubjectID of A) as SubjectID,
                                                                                                            ACCUMULATE(StudentName of A) as StudentName
                                                                                                            )
                                                                                                            );


                                                                                                            Result:



                                                                                                            SubjectID       StudentName
                                                                                                            ---------- -------------
                                                                                                            1 [John, Mary, Sam]
                                                                                                            2 [Alaina, Edward]






                                                                                                            share|improve this answer












                                                                                                            share|improve this answer



                                                                                                            share|improve this answer










                                                                                                            answered Nov 15 '13 at 20:26









                                                                                                            topcheftopchef

                                                                                                            13.4k65092




                                                                                                            13.4k65092






















                                                                                                                1 2
                                                                                                                next




                                                                                                                protected by Community Aug 2 '11 at 14:32



                                                                                                                Thank you for your interest in this question.
                                                                                                                Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                                                                                                                Would you like to answer one of these unanswered questions instead?



                                                                                                                Popular posts from this blog

                                                                                                                Wiesbaden

                                                                                                                Marschland

                                                                                                                Dieringhausen