Sometimes when you're writing an aggregate query in T-SQL you want to concatenate strings in a group together, instead of applying an operation like min, max, or count. The common suggestion is to use FOR XML PATH in a magical way that concatenates for a reason that no one understands (unless you actually take the time to learn the T-SQL XML functionality, which I highly recommend).
I'm going to demonstrate an alternate approach that involves the use of a PIVOT query. In order to use this method, you have to define the maximum number of values that will be combined. This may or may not be a drawback. (In my experience, it's actually a useful sanity check.) If you do it this way, you have a lot more flexibility in join delimiters and the syntax is more straightforward.
-- Prepare example tables. @result is an ordinary data table, and @msg is a
-- related table that stores comments for the records in @result.
DECLARE @result TABLE
(record_id int IDENTITY(1, 1) PRIMARY KEY,
col1 int, col2 int);
DECLARE @msg TABLE
(msg_id int IDENTITY(1, 1) PRIMARY KEY,
record_id int NOT NULL,
msg nvarchar(300) NOT NULL);
INSERT INTO @result (col1, col2)
VALUES (1, 2), (2, 4), (3, 6), (4, 8);
INSERT INTO @msg (record_id, msg)
VALUES
(2, N'first message'),
(2, N'second message'),
(4, N'another message');
-- Use pivoting to concatenate messages for the records together into a
-- single column. A CTE is used to create a temporary result set that joins
-- @result and @msg and includes a column that indicates the message
-- sequence. A pivot query flattens the result set by concatenating the
-- messages together.
WITH q AS
(SELECT [@result].record_id, [@result].col1, [@result].col2,
[@msg].msg,
'Msg' + CONVERT(varchar, ROW_NUMBER() OVER
(PARTITION BY [@msg].record_id
ORDER BY [@msg].msg_id)) AS rn
FROM @result
LEFT JOIN @msg
ON [@result].record_id = [@msg].record_id)
SELECT record_id, col1, col2,
COALESCE(Msg1, '') +
COALESCE(', ' + Msg2, '') +
COALESCE(', ' + Msg3, '') AS msgs
FROM q
PIVOT (MAX(msg) FOR rn IN (Msg1, Msg2, Msg3)) p;
-- Results:
-- +-----------+------+------+-------------------------------+
-- | record_id | col1 | col2 | msgs |
-- +-----------+------+------+-------------------------------+
-- | 1 | 1 | 2 | |
-- | 2 | 2 | 4 | first message, second message |
-- | 3 | 3 | 6 | |
-- | 4 | 4 | 8 | another message |
-- +---------------------------------------------------------+