Это должно дать вам одну строку на пользователя в следующем формате
WITH cte (userId, roleList, roleNameTemp, level)
as
(
SELECT userId
, CAST( '' AS VARCHAR(max) )
, CAST( '' AS VARCHAR(200) )
, 0 level
FROM Role
GROUP BY UserId
UNION ALL
SELECT r.userId
, roleList +
CASE WHEN level = 0 THEN '' ELSE ', ' END + RoleName
, CAST( RoleName AS VARCHAR(200))
, level + 1
FROM CTE c
INNER JOIN Role r ON c.userId = r.userid
WHERE r.RoleName > c.roleNameTemp
)
SELECT UserId
,FirstName
,LastName
,roleList
FROM
(
SELECT u.UserId
,u.FirstName
,u.LastName
,c.roleList
,ROW_NUMBER() OVER (Partition by c.userid order by level desc) rowNumber
FROM cte c
INNER JOIN [User] u on c.userId = u.UserId
) r
WHERE rownumber = 1