STRING_AGG (Transact-SQL)
适用于: sql Server 2017 (14.x) 及更高版本
Azure SQL 数据库 Azure SQL 托管实例
Microsoft Fabric Microsoft Fabric
Warehouse 中的 Azure Synapse Analytics SQL 分析终结点
串联字符串表达式的值,并在其间放置分隔符值。 不能在字符串末尾添加分隔符。
语法
STRING_AGG ( expression , separator ) [ <order_clause> ]
<order_clause> ::=
WITHIN GROUP ( ORDER BY <order_by_expression_list> [ ASC | DESC ] )
参数
expression
任何类型的 表达式。 表达式在串联期间转换为 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、数值、浮点、实际、位、 十进制、smallmoney、货币、日期时间、datetime2 |
nvarchar(4000) |
注解
STRING_AGG
是一个聚合函数,用于提取行中的所有表达式,并将这些表达式串联成一个字符串。 表达式值隐式转换为字符串类型,然后串联在一起。 隐式转换为字符串的过程遵循现有的数据类型转换规则。 有关数据类型转换的详细信息,请参阅 CAST 和 CONVERT。
如果输入表达式的类型 varchar,则分隔符不能 nvarchar类型。
忽略 Null 值,并且不会添加相应的分隔符。 若要返回空值的位置持有者,请使用 ISNULL
函数,如 示例 B所示。
STRING_AGG
适用于任何兼容级别。
注意
<order_clause>
适用于数据库兼容性级别 110 及更高级别。
示例
本文中的 Transact-SQL 代码示例使用 AdventureWorks2022
或 AdventureWorksDW2022
示例数据库,可以从 Microsoft SQL Server 示例和社区项目 主页下载该数据库。
A. 生成以新行分隔的姓名列表
下面的示例在一个结果单元格中生成姓名列表,并将其以回车符分隔。
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
值
下面的示例在一个结果单元格中返回以逗号分隔的姓名,并使用“N/A”替换 null 值。
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, ...
C. 生成采用逗号分隔的值
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 查询编辑器,则 网格 选项无法实现回车。 可切换到“结果显示为文本”,以便正确查看结果集。
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 | 标记 |
---|---|---|
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
。
E. 生成按城市分类的电子邮件列表
下面的查询用于查找员工的电子邮件地址,并将结果按城市分类:
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
结果集如下。
注意
将显示剪裁后的结果。
City | emails |
---|---|
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 ... |
可以直接使用在电子邮件列中返回的电子邮件向在某些特定城市工作的人们发送电子邮件。
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
结果集如下。
注意
将显示剪裁后的结果。
City | 电子邮件 |
---|---|
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 ... |