Comma Seperated list of a one to many relationship put into a single column where it is taking many rows and putting them in a '(char)' seperated list? I use the xml type for this as you can have complex structures that may change over time. Recursion is pretty intense for that sort of thing IMHO.
Here is a self extracting example and below I will explain it:
declare @Person Table ( personID int identity, person varchar(8));
insert into @Person values ('Brett'),('Sean'),('Chad'),('Michael'),('Ray'),('Erik'),('Queyn');
declare @Orders table ( OrderID int identity, PersonID int, Desciption varchar(32), Amount int);
insert into @Orders values (1, 'Shirt', 20),(1, 'Shoes', 50),(2, 'Shirt', 22),(2, 'Shoes', 52),(3, 'Shirt', 20),(3, 'Shoes', 50),(3, 'Hat', 20),(4, 'Shirt', 20),(5, 'Shirt', 20),(5, 'Pants', 30),
(6, 'Shirt', 20),(6, 'RunningShoes', 70),(7, 'Shirt', 22),(7, 'Shoes', 40),(7, 'Coat', 80)
Select top 100
p.person
, o.Desciption
from @Person p
join @Orders o on p.personID = o.PersonID
order by p.person
Select
p.person
, replace(
replace(
replace(
(
select
o.Desciption as d
from @Orders o
where o.PersonID = p.personID
for xml auto
), '"/><o d="', ', ')
, '<o d="', '')
, '"/>', '') as SeperatedList
from @Person p
order by p.person
- I am doing a nested select to get all the child elements (in my example orders) of a parent object (person in my example).
- You cannot return an array in TSQL as a column.... unless it is stored as xml which can be it's own multi elemental tree structure as a single column.
- By nature 'for xml auto' will give me back text instead of the xml type (kind of cool). There is a lot I am leaving out and there is a whole section of white papers on just using 'FOR XML (something)'. Auto assumes the element name is my alias of 'o' though and my column is named 'd' which becomes an attribute.
- Since the cast is done by default to text I don't have to worry about a casting issue because I need to do some find and replaces
- I basically find the labels I applied for my elements and columns and 'replace()' them with a column seperator. I chose ',', you may use whatever you want.
- I replace the end and beginning elements with two more. Voila you now have a '(char)' seperated list.
This method works well as it seperates the child grouping in it's own dataset and from what I have seen is usually pretty fast compared to string operations pasting on to an existing string due to you have to do that method, once plus memory, once plus memory plus memory, once plus memory plus memory.... You get the idea. This method gets everything at once for a dataset and then just evaluates the presentation to the end user instead. If you have millions of child rows and it is slow I would consider dumping to a CTE, table variable, or temp table first and then cast those as XML columns first potentially.