47

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

DECLARE @CodeNameString varchar(100)

SELECT CodeName FROM AccountCodes ORDER BY Sort

我需要将选择查询的所有结果连接到 CodeNameString。

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

4

6 回答 6

93

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

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在第一个字符处放置一个“无”字符,例如消除“多余的”第一个逗号,为您提供您可能的结果寻找。

更新:好的-我理解评论-如果您在数据库表中的文本已经包含字符<>&,那么我当前的解决方案实际上会将这些字符编码为&lt;&gt;&amp;

如果您对该 XML 编码有疑问 - 那么是的,您必须查看 @KM 提出的解决方案,该解决方案也适用于这些字符。我的一个警告:这种方法需要更多的资源和处理密集型 - 就像你知道的那样。

于 2011-03-04T16:24:06.493 回答
28
DECLARE @CodeNameString varchar(max)
SET @CodeNameString=''

SELECT @CodeNameString=@CodeNameString+CodeName FROM AccountCodes ORDER BY Sort
SELECT @CodeNameString
于 2011-03-04T16:18:31.280 回答
12

@AlexanderMP 的答案是正确的,但您也可以考虑使用以下方法处理空值coalesce

declare @CodeNameString  nvarchar(max)
set @CodeNameString = null
SELECT @CodeNameString = Coalesce(@CodeNameString + ', ', '') + cast(CodeName as varchar) from AccountCodes  
select @CodeNameString
于 2011-03-04T16:22:26.100 回答
5

对于 SQL Server 2005 及更高版本,请使用Coalesce,如果有nulls,我将使用Cast 或 Convertnumeric values -

declare @CodeNameString  nvarchar(max)
select  @CodeNameString = COALESCE(@CodeNameString + ',', '')  + Cast(CodeName as varchar) from AccountCodes  ORDER BY Sort
select  @CodeNameString
于 2011-03-04T16:23:00.173 回答
2

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

上面似乎说上面所做的连接是无效的,因为分配可能比选择返回的行多

于 2014-11-25T16:46:54.947 回答
0

这是另一个现实生活中的例子,至少在 2008 版本(及更高版本)中运行良好。

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

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

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

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了我能想到的所有可能的案例问题,并且我们修复了我们得到的数值错误(字段排序)。

于 2014-07-11T10:19:59.170 回答