Also:
DECLARE @Table
TABLE (
col1 INTEGER NOT NULL,
col2 INTEGER NOT NULL,
col3 INTEGER NOT NULL,
col4 INTEGER NOT NULL
);
INSERT @Table (col1, col2, col3, col4) VALUES (1, 2, 3, 4);
INSERT @Table (col1, col2, col3, col4) VALUES (1, 2, 3, 5);
INSERT @Table (col1, col2, col3, col4) VALUES (1, 2, 3, 6);
INSERT @Table (col1, col2, col3, col4) VALUES (1, 2, 3, 7);
INSERT @Table (col1, col2, col3, col4) VALUES (4, 5, 6, 0);
INSERT @Table (col1, col2, col3, col4) VALUES (7, 8, 9, 1);
INSERT @Table (col1, col2, col3, col4) VALUES (7, 8, 9, 2);
INSERT @Table (col1, col2, col3, col4) VALUES (7, 8, 9, 3);
SELECT T1.col1, T1.col2, T1.col3, iTVF2.col4_values
FROM (
SELECT col1, col2, col3
FROM @Table
GROUP BY col1, col2, col3
HAVING COUNT(*) > 1
) T1
CROSS
APPLY (
SELECT ',' + CONVERT(VARCHAR(20), T2.col4)
FROM @Table T2
WHERE T2.col1 = T1.col1
AND T2.col2 = T2.col2
AND T2.col3 = T2.col3
FOR XML PATH('')
) iTVF1 (col4_csv)
CROSS
APPLY (
SELECT STUFF(iTVF1.col4_csv, 1, 1, SPACE(0))
) iTVF2 (col4_values);
Paul White
SQLPerformance.com
SQLkiwi blog
@SQL_Kiwi