patternsqlModerate
Combine column from multiple rows into single row
Viewed 0 times
rowscombinecolumnintosinglemultiplefromrow
Problem
I've got some
The data looks like this:
My results need to look like this:
So for each
My query has to go through the whole table on its own and output these rows. I'm not combining them into multiple columns, one for each row, so
customer_comments split out into multiple rows due to database design, and for a report I need to combine the comments from each unique id into one row. I previously tried something working with this delimited list from SELECT clause and COALESCE trick but I can't recall it and must not have saved it. I can't seem to get it to work in this case either, only seems to work on a single row.The data looks like this:
id row_num customer_code comments
-----------------------------------
1 1 Dilbert Hard
1 2 Dilbert Worker
2 1 Wally LazyMy results need to look like this:
id customer_code comments
------------------------------
1 Dilbert Hard Worker
2 Wally LazySo for each
row_num there's really only one row of results; the comments should be combined in the order of row_num. The above linked SELECT trick works to get all the values for a specific query as one row, but I can't figure out how to make it work as part of a SELECT statement that spits all these rows out. My query has to go through the whole table on its own and output these rows. I'm not combining them into multiple columns, one for each row, so
PIVOT doesn't seem applicable.Solution
This is relatively trivial to do with a correlated subquery. You can't use the COALESCE method highlighted in the blog post you mention unless you extract that to a user-defined function (or unless you only want to return one row at a time). Here is how I typically do this:
If you have a case where the data in comments could contain unsafe-for-XML characters (
To this more elaborate approach:
(Be sure to use the right destination data type,
DECLARE @x TABLE
(
id INT,
row_num INT,
customer_code VARCHAR(32),
comments VARCHAR(32)
);
INSERT @x SELECT 1,1,'Dilbert','Hard'
UNION ALL SELECT 1,2,'Dilbert','Worker'
UNION ALL SELECT 2,1,'Wally','Lazy';
SELECT id, customer_code, comments = STUFF((SELECT ' ' + comments
FROM @x AS x2 WHERE id = x.id
ORDER BY row_num
FOR XML PATH('')), 1, 1, '')
FROM @x AS x
GROUP BY id, customer_code
ORDER BY id;If you have a case where the data in comments could contain unsafe-for-XML characters (
>, <, &), you should change this:FOR XML PATH('')), 1, 1, '')To this more elaborate approach:
FOR XML PATH(''), TYPE).value(N'(./text())[1]', N'varchar(max)'), 1, 1, '')(Be sure to use the right destination data type,
varchar or nvarchar, and the right length, and prefix all string literals with N if using nvarchar.)Code Snippets
DECLARE @x TABLE
(
id INT,
row_num INT,
customer_code VARCHAR(32),
comments VARCHAR(32)
);
INSERT @x SELECT 1,1,'Dilbert','Hard'
UNION ALL SELECT 1,2,'Dilbert','Worker'
UNION ALL SELECT 2,1,'Wally','Lazy';
SELECT id, customer_code, comments = STUFF((SELECT ' ' + comments
FROM @x AS x2 WHERE id = x.id
ORDER BY row_num
FOR XML PATH('')), 1, 1, '')
FROM @x AS x
GROUP BY id, customer_code
ORDER BY id;FOR XML PATH('')), 1, 1, '')FOR XML PATH(''), TYPE).value(N'(./text())[1]', N'varchar(max)'), 1, 1, '')Context
StackExchange Database Administrators Q#17921, answer score: 18
Revisions (0)
No revisions yet.