关于sql server:SQL查询 – 将结果连接成一个字符串

SQL Query - Concatenating Results into One String

本问题已经有最佳答案,请猛点这里访问。

我有一个包含以下代码的SQL函数:

1
2
3
DECLARE @CodeNameString VARCHAR(100)

SELECT CodeName FROM AccountCodes ORDER BY Sort

我需要将select查询的所有结果连接到codenamestring中。

显然,C代码中的foreach循环可以做到这一点,但如何在SQL中做到这一点?


如果您使用的是SQL Server 2005或更高版本,则可以使用此FOR XML PATH & STUFF技巧:

1
2
3
4
5
6
7
8
DECLARE @CodeNameString VARCHAR(100)

SELECT
   @CodeNameString = STUFF( (SELECT ',' + CodeName
                             FROM dbo.AccountCodes
                             ORDER BY Sort
                             FOR XML PATH('')),
                            1, 1, '')

FOR XML PATH('')基本上将字符串连接成一个长的XML结果(类似于,code1,code2,code3等),STUFF在第一个字符处放一个"无"字符,例如删除"多余"的第一个逗号,以得到可能需要的结果。

更新:好的-我理解注释-如果数据库表中的文本已经包含了像<>&这样的字符,那么我当前的解决方案实际上会将这些字符编码为<>&

如果XML编码有问题,那么是的,您必须看看@km提出的解决方案,它也适用于这些字符。我警告你一句:这种方法需要更多的资源和大量的处理——正如你所知道的。


1
2
3
4
5
DECLARE @CodeNameString VARCHAR(MAX)
SET @CodeNameString=''

SELECT @CodeNameString=@CodeNameString+CodeName FROM AccountCodes ORDER BY Sort
SELECT @CodeNameString


@Alexandermp的回答是正确的,但是您也可以考虑使用coalesce处理空值:

1
2
3
4
DECLARE @CodeNameString  nvarchar(MAX)
SET @CodeNameString = NULL
SELECT @CodeNameString = COALESCE(@CodeNameString + ', ', '') + CAST(CodeName AS VARCHAR) FROM AccountCodes  
SELECT @CodeNameString


对于SQL Server 2005及更高版本,使用coalesce for nulls,如果有numeric values,则使用cast或convert。-

1
2
3
DECLARE @CodeNameString  nvarchar(MAX)
SELECT  @CodeNameString = COALESCE(@CodeNameString + ',', '')  + CAST(CodeName AS VARCHAR) FROM AccountCodes  ORDER BY Sort
SELECT  @CodeNameString


在msdn中,不要在select语句中使用变量来连接值(即计算聚合值)。可能会出现意外的查询结果。这是因为选择列表中的所有表达式(包括赋值)不能保证每个输出行只执行一次。

上面似乎说,如上所述的连接是无效的,因为赋值可能比select返回的行要多。


下面是另一个现实生活中的例子,至少在2008年发行版(以及更高版本)中效果良好。

这是原始查询,它使用简单的max()来获取至少一个值:

1
2
3
SELECT option_name, Field_M3_name, MAX(Option_value) AS"Option value", MAX(Sorting) AS"Sorted"
FROM Value_list GROUP BY Option_name, Field_M3_name
ORDER BY option_name, Field_M3_name

改进版,主要改进是显示所有值,用逗号分隔:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT from1.keys, from1.option_name, from1.Field_M3_name,

 Stuff((SELECT DISTINCT ', ' + [Option_value] FROM Value_list from2
  WHERE COALESCE(from2.Option_name,'') + '|' + COALESCE(from2.Field_M3_name,'') = from1.keys FOR XML PATH(''),TYPE)
  .value('text()[1]','nvarchar(max)'),1,2,N'') AS"Option values",

 Stuff((SELECT DISTINCT ', ' + CAST([Sorting] AS VARCHAR) FROM Value_list from2
  WHERE COALESCE(from2.Option_name,'') + '|' + COALESCE(from2.Field_M3_name,'') = from1.keys FOR XML PATH(''),TYPE)
  .value('text()[1]','nvarchar(max)'),1,2,N'') AS"Sorting"

FROM ((SELECT DISTINCT COALESCE(Option_name,'') + '|' + COALESCE(Field_M3_name,'') AS KEYS, Option_name, Field_M3_name FROM Value_list)
-- WHERE
) from1
ORDER BY KEYS

注意,我们已经解决了我能想到的所有可能的NULL案例问题,还修复了数值(字段排序)的错误。