Группировка по стране еще добавит сложности. Но мы не будем этого делать, поскольку в SQL Server, начиная с версии 2017, появилась функция STRING_AGG, позволяющая конкатенировать строки. Эта функция имеет два обязательных аргумента - строковое выражение, которое и будет использоваться для сцепления, и разделитель.
SELECT country, STRING_AGG(name,',') ships_list
FROM Ships s JOIN Classes c ON s.class=c.class
GROUPBY country
ORDERBY country;
country
ships_list
Gt.Britain
Renown,Repulse,Resolution,Ramillies,Revenge,Royal Oak,Royal Sovereign
Japan
Musashi,Yamato,Haruna,Hiei,Kirishima,Kongo
USA
North Carolina,South Dakota,Washington,Iowa,Missouri,New Jersey,Wisconsin,California,Tennessee
Из представленного результата видно, что корабли в списке не отсортированы. Сортировка в стиле GROUP_CONCAT здесь не работает. Чтобы задать порядок сортировки, используется необязательное предложение WITHIN GROUP:
SELECT country, STRING_AGG(name,',') WITHIN GROUP(ORDERBY name) ships_list
FROM Ships s JOIN Classes c ON s.class=c.class
GROUPBY country
ORDERBY country;
country
ships_list
Gt.Britain
Ramillies,Renown,Repulse,Resolution,Revenge,Royal Oak,Royal Sovereign
При использовании функции STRING_AGGсоединяемые значения преобразуются к типу данных VARCHAR (NVARCHAR).
Типом результата будет VARCHAR(8000) или NVARCHAR(4000), если среди соединяемых значений не будет значений типа VARCHAR(MAX) или NVARCHAR(MAX). В последнем случае результат будет иметь тип VARCHAR(MAX) (или NVARCHAR(MAX) соответственно).
В нижеследующем примере будет получена ошибка, поскольку длина результата - 8011 - превышает значение 8000:
8000 (значение 'a' будет дополнено пробелами, т.к. используется тип постоянной длины CHAR),
1 символ на запятую-разделитель,
10 (длина значения 'bbbbbbbbbb').
declare @a char(8000), @b varchar(10);
SELECT @a='a',@b=replicate('b',10);
SELECT string_agg(x,',') res
FROM(VALUES(@b),(@a)) X(x);
Результат агрегирования STRING_AGG превышает предел в 8000 байтов. Используйте типы LOB, чтобы избежать усечения результатов.
Однако если, скажем, для переменной @b мы используем тип VARCHAR(MAX), то код выполнится без ошибки: