Creating a comma separated list from a table or converting multiple rows into single row along with delimiter was never been easier in earlier (before SQL Server 2017) version of SQL Server. I have written a detailed article back in 2012 regarding this issue, where I used CURSOR, COALESCE() function, STUFF() function & XML format etc. to achieve it.
In SQL Server 2017, a new function shipped namely STRING_AGG() which can help you to achieve above mentioned functionality by using this function ONLY. By the way, instead of comma ( , ) you can use semi-colon ( ; ) or any other delimiters, it works like a charm with all delimiters.
Let me demonstrate STRING_AGG() functionality by giving some examples. I am going to use Customers table in Northwind database as shown below, which can be downloaded from here.
Sample:
As you can see in below sample table that there are many companies in each country.
USE Northwind GO SELECT [Country] , [CompanyName] FROM [dbo].[Customers] ORDER BY [Country]; GO --OUTPUT

Example 1:
In the below example, I created a company list separated by comma (delimiter) for each country. You can use any delimiter based on your requirement.
USE Northwind GO SELECT [Country] , STRING_AGG(CompanyName,', ') AS [CompanyName] FROM [dbo].[Customers] GROUP BY [Country] ORDER BY [Country]; GO --OUTPUT

Example 2:
In the above example 1, I got comma-separated list of companies for each country but the issue is those company names do NOT display in an alphabetical sort order. To resolve it we are going to use WITHIN GROUP ORDER BY clause within function as shown below:
USE Northwind GO SELECT [Country] ,STRING_AGG(CompanyName,', ') WITHIN GROUP (ORDER BY CompanyName) AS [CompanyName] FROM [dbo].[Customers] GROUP BY [Country] ORDER BY [Country]; GO --OUTPUT

Example 3:
In this example, I want to get list of comma separated OrderID(s) for each Company but the data does NOT exists in one table, so I will join two tables (Customers, Orders) to be able to retrieve the data as shown below.
USE Northwind GO SELECT [CompanyName] , STRING_AGG(OrderID,',') AS OrderIDs FROM [Customers] INNER JOIN [Orders] ON [Customers].[CustomerID]=[Orders].[CustomerID] GROUP BY [CompanyName]; GO --OUTPUT

Conclusion:
I use STRING_AGG() function in my day to day SQL scripting quite frequently, I found it very handy. Do let me know if you use this function in your development and how did you find it?
Leave a Reply