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
或 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
。 默认的排序顺序为升序。
返回类型
返回类型取决于第一个参数(表达式)。 如果输入参数是字符串类型(NVARCHAR
VARCHAR
,则结果类型与输入类型相同。 下表列出了自动转换:
输入表达式类型 | 结果 |
---|---|
NVARCHAR(MAX) | NVARCHAR(MAX) |
VARCHAR(MAX) | VARCHAR(MAX) |
NVARCHAR(1...4000) | NVARCHAR(4000) |
VARCHAR(1...8000) | VARCHAR(8000) |
int, bigint, smallint, tinyint, numeric, float, real, bit, decimal, smallmoney, money, datetime, datetime2, | NVARCHAR(4000) |
注解
STRING_AGG
是一个聚合函数,用于提取行中的所有表达式,并将这些表达式串联成一个字符串。 表达式值隐式转换为字符串类型,然后串联在一起。 隐式转换为字符串的过程遵循现有的数据类型转换规则。 有关数据类型转换的详细信息,请参阅 CAST 和 CONVERT (Transact-SQL)。
如果输入表达式的类型为 VARCHAR
,则分隔符的类型不能是 NVARCHAR
。
null 值会被忽略,且不会添加相应的分隔符。 若要为 null 值返回占位符,请使用 ISNULL
函数,如示例 B 中所示。
STRING_AGG
适用于任何兼容级别。
注意
<order_clause>
适用于数据库兼容性级别 110 及更高级别。
示例
本文中的大多数示例都引用 AdventureWorks 示例数据库。
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 ... |
结果中未返回 name
单元格中的 NULL
值。
注意
如果使用 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
结果集如下。
注意
将显示剪裁后的结果。
姓名 |
---|
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 JOIN dbo.ArticleTag AS t
ON a.ArticleId = t.ArticleId
GROUP BY a.articleId, title;
GO
结果集如下。
articleId | title | 标记 |
---|---|---|
172 | 参选方民调结果不相上下 | 政治,民意调查,市参议会 |
176 | 新高速公路有望减少交通拥塞 | Null |
177 | 狗继续比猫更受人喜爱 | 民意调查,动物 |
注意
如果 STRING_AGG
函数不是 SELECT
列表中的唯一项,则需要子句 GROUP BY
。
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... |
后续步骤
在以下文章中了解有关 Transact-SQL 函数的详细信息: