SQL Query - объединение результатов в одну строку

У меня есть функция sql, которая включает этот код:

DECLARE @CodeNameString varchar(100)

SELECT CodeName FROM AccountCodes ORDER BY Sort

Мне нужно объединить все результаты из запроса select в CodeNameString.

Очевидно, что цикл FOREACH в коде С# будет делать это, но как это сделать в SQL?

Ответ 1

Если вы используете 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, которое работает и для этих символов. Одно слово предупреждение от меня: этот подход намного больше ресурса и интенсивной обработки - просто так вы знаете.

Ответ 2

DECLARE @CodeNameString varchar(max)
SET @CodeNameString=''

SELECT @[email protected]+CodeName FROM AccountCodes ORDER BY Sort
SELECT @CodeNameString

Ответ 3

@Ответ на AlexanderMP верен, но вы также можете рассмотреть возможность обработки нулей с помощью coalesce:

declare @CodeNameString  nvarchar(max)
set @CodeNameString = null
SELECT @CodeNameString = Coalesce(@CodeNameString + ', ', '') + cast(CodeName as varchar) from AccountCodes  
select @CodeNameString

Ответ 4

Для SQL Server 2005 и выше используйте Coalesce для nulls, и я использую Включить или преобразовать, если есть numeric values -

declare @CodeNameString  nvarchar(max)
select  @CodeNameString = COALESCE(@CodeNameString + ',', '')  + Cast(CodeName as varchar) from AccountCodes  ORDER BY Sort
select  @CodeNameString

Ответ 5

from msdn Не используйте переменную в инструкции SELECT для конкатенации значений (то есть для вычисления суммарных значений). Возможны неожиданные результаты запроса. Это связано с тем, что все выражения в списке SELECT (включая присваивания) не гарантируются для выполнения только один раз для каждой выходной строки

Выше кажется, что конкатенация, как сделано выше, неверна, поскольку назначение может выполняться больше раз, чем есть строки, возвращаемые select

Ответ 6

Вот еще один пример реальной жизни, который отлично работает как минимум с выпуском 2008 года (и позже).

Это исходный запрос, который использует простой max() для получения хотя бы одного из значений:

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, о которых я могу думать, а также мы исправили ошибку, полученную для числовых значений (сортировка полей).