STRING_AGG (Transact-SQL)
Область применения: SQL Server 2017 (14.x) и более поздних
версий База данных SQL Azure Управляемый экземпляр SQL Azure
конечной точке аналитики SQL Azure Synapse Analytics
в хранилище Microsoft Fabric
в Microsoft Fabric
Сцепляет значения строковых выражений, помещая между ними значения-разделители. В конце строки разделитель не добавляется.
Соглашения о синтаксисе Transact-SQL
Синтаксис
STRING_AGG ( expression , separator ) [ <order_clause> ]
<order_clause> ::=
WITHIN GROUP ( ORDER BY <order_by_expression_list> [ ASC | DESC ] )
Аргументы
выражение
Выражение любого типа. Выражения преобразуются в nvarchar или типы varchar во время объединения. Типы, отличные от строк, преобразуются в тип nvarchar .
separator
Выражение nvarchar или тип varchar, используемый в качестве разделителя для объединенных строк. Может быть литералом или переменной.
<order_clause>
При необходимости укажите очередность сцепляемых результатов с помощью предложения WITHIN GROUP
:
WITHIN GROUP ( ORDER BY <order_by_expression_list> [ ASC | DESC ] )
<order_by_expression_list>
Список неконстантных выражений, который можно использовать для сортировки результатов. В запросе допускается только один аргумент
<order_by_expression_list>
. По умолчанию задан порядок сортировки по возрастанию.
Возвращаемые типы
Тип возвращаемого значения зависит от первого аргумента (выражения). Если входной аргумент является строковым типом (nvarchar, varchar), тип результата совпадает с типом входных данных. В приведенной ниже таблице перечислены автоматические преобразования.
Тип входного выражения | Результат |
---|---|
nvarchar(max) | nvarchar(max) |
varchar(max) | varchar(max) |
nvarchar(1..4000) | nvarchar(4000) |
varchar(1..8000) | varchar(8000) |
int, bigint, smallint, tinyint, числовой, float, реальные, бит, десятичные, smallmoney, деньги, datetime, datetime2 |
nvarchar(4000) |
Замечания
STRING_AGG
— это агрегатная функция, которая принимает все выражения из строк и сцепляет их в одну строку. Значения выражений неявно преобразуются в строковые типы и затем сцепляются. Неявное преобразование в строки выполняется по существующим правилам преобразования типов данных. Дополнительные сведения о преобразованиях типов данных см. в разделе CAST и CONVERT.
Если входное выражение является типом varchar, разделитель не может быть типом nvarchar.
Значения NULL игнорируются, а соответствующий разделитель не добавляется. Чтобы вернуть заполнитель для значений NULL, используйте функцию ISNULL
, как показано в примере B.
Функция STRING_AGG
доступна на любом уровне совместимости.
Примечание.
<order_clause>
доступна с уровнем совместимости базы данных 110 и выше.
Примеры
Примеры кода Transact-SQL в этой статье используют пример базы данных AdventureWorks2022
или AdventureWorksDW2022
, которую можно скачать на домашней странице примеров Microsoft SQL Server и проектов сообщества.
А. Формирование списка имен, разделенного по строкам
В приведенном ниже примере формируется список имен в одной результирующей ячейке, разделенный символами возврата каретки.
USE AdventureWorks2022;
GO
SELECT STRING_AGG(CONVERT (NVARCHAR (MAX), FirstName), CHAR(13)) AS csv
FROM Person.Person;
GO
Вот результирующий набор.
csv
-----------
Syed
Catherine
Kim
Kim
Kim
Hazem
...
Значения NULL
, найденные в ячейках name
, не возвращаются в результатах.
Примечание.
Если используется редактор запросов SQL Server Management Studio, параметр Результаты в сетку не может реализовать возврат каретки. Чтобы результирующий набор отображался правильно, перейдите в режим В виде текста. По умолчанию результаты в виде текста усекаются до 256 символов. Чтобы увеличить это ограничение, измените значение параметра Максимальное число символов, отображаемых в каждом столбце.
B. Создание списка имен, разделенных запятыми без NULL
значений
В приведенном ниже примере значения NULL заменяются на "N/A" и имена, разделенные запятыми, возвращаются в одной результирующей ячейке.
USE AdventureWorks2022;
GO
SELECT STRING_AGG(CONVERT (NVARCHAR (MAX), ISNULL(FirstName, 'N/A')), ',') AS csv
FROM Person.Person;
GO
Вот обрезанный результирующий набор.
csv
-----
Syed,Catherine,Kim,Kim,Kim,Hazem,Sam,Humberto,Gustavo,Pilar,Pilar, ...
В. Формирование списка значений с разделителями-запятыми
USE AdventureWorks2022;
GO
SELECT STRING_AGG(CONVERT (NVARCHAR (MAX), CONCAT(FirstName, ' ', LastName, '(', ModifiedDate, ')')), CHAR(13)) AS names
FROM Person.Person;
GO
Вот обрезанный результирующий набор.
names
-------
Ken Sánchez (Feb 8 2003 12:00AM)
Terri Duffy (Feb 24 2002 12:00AM)
Roberto Tamburello (Dec 5 2001 12:00AM)
Rob Walters (Dec 29 2001 12:00AM)
...
Примечание.
Если используется редактор запросов Management Studio, параметр results to Grid не может реализовать возврат каретки. Чтобы результирующий набор отображался правильно, перейдите в режим В виде текста.
D. Получение новых статей со связанными тегами
Представьте базу данных, в которой статьи и их теги разделены по разным таблицам. Разработчику необходимо вернуть одну строку для каждой статьи со всеми связанными тегами. Этот результат имеет следующий запрос:
SELECT a.articleId,
title,
STRING_AGG(tag, ',') AS tags
FROM dbo.Article AS a
LEFT OUTER JOIN dbo.ArticleTag AS t
ON a.ArticleId = t.ArticleId
GROUP BY a.articleId, title;
GO
Вот результирующий набор.
articleId | title | tags |
---|---|---|
172 |
Polls indicate close election results |
politics,polls,city council |
176 |
New highway expected to reduce congestion |
NULL |
177 |
Dogs continue to be more popular than cats |
polls,animals |
Примечание.
Предложение GROUP BY
является обязательным, если функция STRING_AGG
не является единственным элементом в списке SELECT
.
Е. Формирование списка адресов электронной почты по городам
Следующий запрос находит адреса электронной почты сотрудников и группирует их по городам:
USE AdventureWorks2022;
GO
SELECT TOP 10 City,
STRING_AGG(CONVERT (NVARCHAR (MAX), EmailAddress), ';') AS emails
FROM Person.BusinessEntityAddress AS BEA
INNER JOIN Person.Address AS A
ON BEA.AddressID = A.AddressID
INNER JOIN Person.EmailAddress AS EA
ON BEA.BusinessEntityID = EA.BusinessEntityID
GROUP BY City;
GO
Вот результирующий набор.
Примечание.
Результирующий набор отображается обрезанным.
Город | сообщений электронной почты |
---|---|
Ballard |
paige28@adventure-works.com ;joshua24@adventure-works.com ;javier12@adventure-works.com ; ... |
Baltimore |
gilbert9@adventure-works.com |
Barstow |
kristen4@adventure-works.com |
Basingstoke Hants |
dale10@adventure-works.com ;heidi9@adventure-works.com |
Baytown |
kelvin15@adventure-works.com |
Beaverton |
billy6@adventure-works.com ;dalton35@adventure-works.com ;lawrence1@adventure-works.com ; ... |
Bell Gardens |
christy8@adventure-works.com |
Bellevue |
min0@adventure-works.com ;gigi0@adventure-works.com ;terry18@adventure-works.com ; ... |
Bellflower |
philip0@adventure-works.com ;emma34@adventure-works.com ;jorge8@adventure-works.com ; ... |
Bellingham |
christopher23@adventure-works.com ;frederick7@adventure-works.com ;omar0@adventure-works.com ; ... |
Адреса, возвращенные в столбце emails, можно использовать для рассылки сообщений группе людей, работающих в определенном городе.
F. Формирование отсортированного списка адресов электронной почты по городам
Так же как в предыдущем примере, следующий запрос находит адреса электронной почты сотрудников, группирует их по городам и сортирует по алфавиту:
USE AdventureWorks2022;
GO
SELECT TOP 10 City,
STRING_AGG(CONVERT (NVARCHAR (MAX), EmailAddress), ';') WITHIN GROUP (ORDER BY EmailAddress ASC) AS Emails
FROM Person.BusinessEntityAddress AS BEA
INNER JOIN Person.Address AS A
ON BEA.AddressID = A.AddressID
INNER JOIN Person.EmailAddress AS EA
ON BEA.BusinessEntityID = EA.BusinessEntityID
GROUP BY City;
GO
Вот результирующий набор.
Примечание.
Результирующий набор отображается обрезанным.
Город | Сообщения электронной почты |
---|---|
Barstow |
kristen4@adventure-works.com |
Basingstoke Hants |
dale10@adventure-works.com ;heidi9@adventure-works.com |
Braintree |
mindy20@adventure-works.com |
Bell Gardens |
christy8@adventure-works.com |
Byron |
louis37@adventure-works.com |
Bordeaux |
ranjit0@adventure-works.com |
Carnation |
don0@adventure-works.com ;douglas0@adventure-works.com ;george0@adventure-works.com ; ... |
Boulogne-Billancourt |
allen12@adventure-works.com ;bethany15@adventure-works.com ;carl5@adventure-works.com ; ... |
Berkshire |
barbara41@adventure-works.com ;brenda4@adventure-works.com ;carrie14@adventure-works.com ; ... |
Berks |
adriana6@adventure-works.com ;alisha13@adventure-works.com ;arthur19@adventure-works.com ; ... |