2

私はデータの表を持っています:

|Key|Field |DateField |
|A  |Value1|2012-06-01|
|A  |Value2|2012-06-02|
|A  |Value3|2012-06-03|
|B  |Value4|2012-06-04|
|B  |Value5|2012-06-05|

グループのように、この文字列データをキーごとに集計したいのですが、その方法がわかりません。最終的には次のようになります。

|Key|Field Aggregate       |
|A  |Value1, Value2, Value3|
|B  |Value4, Value5        |

さらに良いのは、シーケンスの順序が対応する日付フィールドの順序によって決定されるアグリゲーションに挿入されたシーケンスの位置で終わることです。

|Key|Field Aggregate                |
|A  |1: Value1, 2: Value2, 3: Value3|
|B  |1: Value4, 2: Value5           |

これは、共通テーブル式を使用して実行できることのように見えますが、その方法を理解できないようです。

通常、SQLでこの種の操作を実行することはありません。通常、データをアプリにプルし、必要に応じてコードで操作します。

残念ながら、この場合、これはオプションではないようです。

SQL Server2005T-SQLでこれを行うにはどうすればよいですか。

CTEは正しいアプローチですか?もっと適切なものはありますか?

4

1 に答える 1

4

このサンプルデータを考えると:

CREATE TABLE #t
(
  [Key]     char(1),
  [Field]   varchar(32), 
  DateField datetime
);

INSERT #t([Key],[Field],DateField) 
  SELECT 'A','Value1','20120601'
  UNION ALL SELECT 'A','Value2','20120602'
  UNION ALL SELECT 'A','Value3','20120603'
  UNION ALL SELECT 'B','Value4','20120604'
  UNION ALL SELECT 'B','Value5','20120605';

SQL Server2017より古いバージョンのSQLServerでは、次のことができます。

SELECT [Key], [Field Aggregate] = STUFF(
  (SELECT ', ' + CONVERT(varchar(11), 
      ROW_NUMBER() OVER (PARTITION BY [Key] ORDER BY DateField)) 
      + ': ' + [Field]
    FROM #t AS t2 WHERE t2.[Key] = t.[Key]
    ORDER BY DateField
    FOR XML PATH(''), 
    TYPE).value(N'./text()[1]', N'varchar(max)'), 1, 2, '')
  FROM #t AS t
  GROUP BY [Key] ORDER BY [Key];

結果:

フィールドアグリゲート
A 1:値1、2:値2、3:値3
B 1:Value4、2:Value5

SQL Server 2017以降では、以下を使用する方がはるかに簡単ですSTRING_AGG()

;WITH cte AS
(
  SELECT [Key], [Field], rn = ROW_NUMBER() OVER 
    (PARTITION BY [Key] ORDER BY DateField)
    FROM #t
)
SELECT [Key], [Field Aggregate] = STRING_AGG(
    CONCAT(rn, ': ', [Field]), ', ')
    WITHIN GROUP (ORDER BY rn) 
  FROM cte
  GROUP BY [Key] ORDER BY [Key];
于 2012-07-03T02:20:38.177 に答える