複数行で先行するコンマなしでCOALESCEを使用する方法は?


27

私は次を達成しようとしています:

California | Los Angeles, San Francisco, Sacramento
Florida    | Jacksonville, Miami

残念ながら、私は「ロサンゼルス、サンフランシスコ、サクラメント、ジャクソンビル、マイアミ」を取得しています

STUFF関数を使用して目的の結果を達成できますが、COALESCEを使用してよりクリーンな方法があるかどうか疑問に思っていましたか?

STATE       | CITY
California  | San Francisco
California  | Los Angeles
California  | Sacramento
Florida     | Miami
Florida     | Jacksonville 


DECLARE @col NVARCHAR(MAX);
SELECT @col= COALESCE(@col, '') + ',' + city
FROM tbl where city = 'California';
SELECT @col;

ありがとう

回答:


45

これはあなたが望んでいるよりクリーンなアプローチかもしれません。基本的に、変数がまだ初期化されているかどうかを確認します。そうでない場合は、空の文字列に設定し、最初の都市を追加します(先頭のコンマなし)。ある場合は、カンマを追加してから、都市を追加します。

DECLARE @col nvarchar(MAX);
SELECT @col = COALESCE(@col + ',', '') + city
  FROM dbo.tbl WHERE state = 'California';

もちろん、状態ごとに変数を設定する場合にのみ機能します。各状態のリストを一度に1つずつ引き出している場合、1つのショットでより良い解決策があります。

SELECT [state], cities = STUFF((
    SELECT N', ' + city FROM dbo.tbl
    WHERE [state] = x.[state]
    FOR XML PATH(''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 2, N'')
FROM dbo.tbl AS x
GROUP BY [state]
ORDER BY [state];

結果:

state       cities
----------  --------------------------------------
California  San Francisco, Los Angeles, Sacramento  
Florida     Miami, Jacksonville

各州内の都市名で並べ替えるには:

SELECT [state], cities = STUFF((
    SELECT N', ' + city FROM dbo.tbl
    WHERE [state] = x.[state]
    ORDER BY city
    FOR XML PATH(''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 2, N'')
FROM dbo.tbl AS x
GROUP BY [state]
ORDER BY [state];

Azure SQL DatabaseまたはSQL Server 2017+では、新しいSTRING_AGG()関数を使用できます。

SELECT [state], cities = STRING_AGG(city, N', ')
  FROM dbo.tbl
  GROUP BY [state]
  ORDER BY [state];

そして都市名で並べ替え:

SELECT [state], cities = STRING_AGG(city, N', ') 
                         WITHIN GROUP (ORDER BY city)
  FROM dbo.tbl
  GROUP BY [state]
  ORDER BY [state];

アーロンに感謝します。私の現在のソリューションは、GROUP BYの代わりにDISTINCTを使用していることを除いて、ほぼ同じです。
user2732180 14年

2
@ user2732180状態ごとに連結を実行する可能性が高いため、GROUP BYを使用する必要があります。DISTINCTを使用すると、たとえば、カリフォルニアのすべてのインスタンスに同じ連結が適用され、それらの複製を生成したすべての作業が破棄されます。
アーロンバートランド

6

上記のアーロンの答えに加えて...

ORDER BYクエリの最後の項目のみを含めると、破損する可能性があることに注意してください。私の場合、グループ化していないので、それが違いを生むかどうかはわかりません。SQL 2014を使用しています。私の場合、value1、value2、value3 ...のようなものがありますが、変数の結果はvalue3のみでした。


アーロンは次のようにコメントしました。

これは、Connectで少なくとも4回報告されています。

  1. 変数の連結とフィルターによる結果(where条件など)
  2. (n)ORDER BYが追加されると、ResultSetからのvarchar構築が失敗する
  3. CROSS APPLYとテーブル値関数を使用して、順序付けられたSELECTからローカル変数を割り当てると、最後の値のみが返される
  4. テーブル変数からvarchar(max)/ nvarchar(max)値を連結するときに、非プライマリキー列によるフィルタリングと順序付けを行うと、誤った結果が返される場合があります

Microsoftからの応答例:

表示されている動作は仕様です。ORDER BY句を含むクエリで割り当て操作(この例では連結)を使用すると、動作が未定義になります。

応答はKB 287515も参照します。

PRB:実行計画と集計連結クエリの結果は式の場所に依存

解決策はFOR XML PATH、連結の順序が重要な場合、そしてもちろん、すべての値を確実に含める必要がある場合に(Aaronの答えの2番目のアプローチ)を使用することです。以下も参照してください。

nvarchar連結/インデックス/スタックオーバーフローでのnvarchar(max)不可解な動作

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.