web-dev-qa-db-ja.com

SQLクエリ-結果を1つの文字列に連結する

このコードを含むSQL関数があります。

DECLARE @CodeNameString varchar(100)

SELECT CodeName FROM AccountCodes ORDER BY Sort

選択クエリのすべての結果をCodeNameStringに連結する必要があります。

C#コードのFOREACHループがこれを行うことは明らかですが、SQLでどのように行うのですか?

34
Matthew Jones

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('')は基本的に文字列を1つの長いXML結果(_,code1,code2,code3_などのようなもの)に連結し、STUFFは最初の文字に「何もない」文字を置きます。 「余分な」最初のコンマを消去し、おそらく探している結果を提供します。

PDATE: OK-コメントを理解しています-データベーステーブルのテキストに_<_、_>_または_&_などの文字が既に含まれている場合、私の現在のソリューションは、実際にそれらを_&lt;_、_&gt;_、および_&amp;_にエンコードします。

そのXMLエンコードに問題がある場合-はい、それらの文字に対しても機能する@KMによって提案されたソリューションを確認する必要があります。 警告私からの1つの言葉:このアプローチはさらに多くリソースと処理が集中的です-ちょうどあなたが知っています。

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

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

@AlexanderMPの答えは正しいですが、coalesceを使用してnullを処理することも検討できます。

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

SQL Server 2005以降では、nullsCoalesce を使用し、numeric valuesがある場合は CastまたはConvert を使用します-

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

from msdn値を連結する(つまり、集計値を計算する)ためにSELECTステートメントで変数を使用しないでください。予期しないクエリ結果が発生する場合があります。これは、SELECTリスト内のすべての式(割り当てを含む)が各出力行に対して一度だけ実行されることが保証されていないためです。

上記は、上記で行われた連結は、selectによって返される行があるよりも多くの回数割り当てが行われる可能性があるため無効であると言っているようです。

2
peter

少なくとも2008リリース(およびそれ以降)で正常に動作する別の実際の例を次に示します。

これは、単純なmax()を使用して少なくとも1つの値を取得する元のクエリです。

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ケースの問題を解決したことに加えて、数値に対して得られたエラーを修正したことに注意してください(フィールドの並べ替え)。

0
Timo Riikonen