web-dev-qa-db-ja.com

COALESCEを複数の行で、前にコンマを付けずに使用するにはどうすればよいですか?

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

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;

ありがとう

29
user2732180

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

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

もちろん、これは状態ごとに変数を設定する場合にのみ機能します。各州のリストを一度に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];
_
47
Aaron Bertrand

Aaron's answer 上記に追加するだけです...

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


アーロンは言った:

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

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

Microsoftからの応答例:

表示されている動作は仕様によるものです。 ORDER BY句のあるクエリで代入演算(この例では連結)を使用すると、動作が未定義になります。

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

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

解決策はFOR XML PATH(アーロンの回答の2番目のアプローチ)連結の順序が重要な場合、そしてもちろん、すべての値を確実に含める必要がある場合。こちらもご覧ください:

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

7
ebol2000