Поскольку вы используете SQL Server 2017, вы можете использовать функцию STRING_AGG
SELECT
p.PersonID,
STRING_AGG( Language + '(' +
CASE cvnl.Proficiency
WHEN 1 THEN 'Good'
WHEN 2 THEN 'Very Good'
THEN 3 THEN 'Excellent'
END + ')'
, CHAR(13) + CHAR(10)) AS Languages
FROM CV_Certifications cv
JOIN person p on cv.PersonID = p.PersonID
JOIN CV_NewLanguages cvnl on cvnl.PersonID = p.PersonID
JOIN Languages l on l.LanguageID = cvnl.LanguageID
WHERE active=1
GROUP BY p.PersonID,
ORDER BY p.PersonID
Вы упоминаете, что она нужна для AspxGridview, поэтому вам может понадобиться разрыв HTML тоже
SELECT
p.PersonID,
STRING_AGG( Language + '(' +
CASE cvnl.Proficiency
WHEN 1 THEN 'Good'
WHEN 2 THEN 'Very Good'
THEN 3 THEN 'Excellent'
END + ')'
, CHAR(13) + CHAR(10) + '<BR/>' + CHAR(13) + CHAR(10)) AS Languages
FROM CV_Certifications cv
JOIN person p on cv.PersonID = p.PersonID
JOIN CV_NewLanguages cvnl on cvnl.PersonID = p.PersonID
JOIN Languages l on l.LanguageID = cvnl.LanguageID
WHERE active=1
GROUP BY p.PersonID,
ORDER BY p.PersonID
Если вы используете предыдущую версию SQL или хотите продолжать использовать STUFF, вы можете ЗАМЕНИТЬ запятую из результата вашего STUFF
SELECT
p.PersonID,
REPLACE(
STUFF( (
SELECT ',' + l.Language +' (' +
CASE cvnl.Proficiency
WHEN 1 THEN 'Good'
WHEN 2 THEN 'Very Good'
WHEN 3 THEN 'Excellent'
END +') '
FROM CV_NewLanguages cvnl
JOIN Languages l on l.LanguageID = cvnl.LanguageID
WHERE cvnl.PersonID = p.PersonID
ORDER BY l.Language ASC
FOR XML PATH(''))
, 1, 1, '')
,',',CHAR(13) + CHAR(10)) AS Languages
FROM person p
WHERE EXISTS (SELECT 1 FROM CV_Certifications cv WHERE cv.PersonID = p.PersonID)
AND EXISTS (SELECT 1 FROM CV_NewLanguages cvnl WHERE cvnl.PersonID = p.PersonID
AND active=1
ORDER BY p.PersonID
Я также взял на себя свободу немного настроить ваш запрос