How to use the FOR XML keywords in SQL to concatenate ids
Part three of a three-part series of blogs

If you want to group items in a SQL query, showing a comma-delimited list of ids for each, generating an XML file is not the obvious place to start - but it should be.

  1. Using FOR XML in SQL to group and concatenate ids
  2. Generating XML from SQL using FOR XML PATH
  3. Combining grouping, STUFF and FOR XML in a single query (this blog)

Posted by Andy Brown on 27 September 2016

You need a minimum screen resolution of about 700 pixels width to see our blogs. This is because they contain diagrams and tables which would not be viewable easily on a mobile phone or small laptop. Please use a larger tablet, notebook or desktop computer, or change your screen resolution settings.

Combining grouping, STUFF and FOR XML in a single query

I'm gradually sneaking up on the final answer to the challenge I set at the start of this blog.

The basic GROUP BY query shell

What we want to do is to replace the selected text in this query:

Query with text to replace

Instead of displaying Answer here, we want to show the list of course ids, comma-separated.

 

This will allow us to show the course ids in the second column of the query output:

Answer column

Here's what we get for now.

 

Final digression - the STUFF function in SQL

One last bit of SQL we'll need is the STUFF function, which takes four arguments:

Argument What it contains Example
1 String to search 'Wise Owl Training'
2 Where to start 6
3 How many characters to replace 3
4 Text to put instead 'Frog'

The example above could be shown using this statement:

-- rename Wise Owl

SELECT STUFF('Wise Owl Training', 6, 3, 'Frog')

This would produce this when run:

Wise Frog Training

A better name? Perhaps not.

 

For our example, we can use the STUFF function to get rid of the opening comma at the start of each list.

The final SQL query

So here's the final query:

-- show course ids for each person

SELECT

p.PersonName,

STUFF((

SELECT ',' + CAST(innerTable.CourseId AS varchar(10))

FROM tblPerson AS innerTable

WHERE innerTable.PersonName = p.PersonName

FOR XML PATH('')

),1,1,'') AS Ids

FROM

tblPerson AS p

GROUP BY

p.PersonName

This produces the following results:

Query results

The output from running the above query.

 

This uses a correlated subquery to list out two columns for each person:

  1. The name of the person.
  2. The XML text listing the course ids for this person, with all node names and the leading comma removed.

Hopefully this now makes sense!

  1. Using FOR XML in SQL to group and concatenate ids
  2. Generating XML from SQL using FOR XML PATH
  3. Combining grouping, STUFF and FOR XML in a single query (this blog)
This blog has 0 threads Add post