解決
最適の定義はさまざまですが、通常のTransactSQLを使用してさまざまな行の文字列を連結する方法を次に示します。これはAzureで正常に機能するはずです。
;WITH Partitioned AS
(
SELECT
ID,
Name,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Name) AS NameNumber,
COUNT(*) OVER (PARTITION BY ID) AS NameCount
FROM dbo.SourceTable
),
Concatenated AS
(
SELECT
ID,
CAST(Name AS nvarchar) AS FullName,
Name,
NameNumber,
NameCount
FROM Partitioned
WHERE NameNumber = 1
UNION ALL
SELECT
P.ID,
CAST(C.FullName + ', ' + P.Name AS nvarchar),
P.Name,
P.NameNumber,
P.NameCount
FROM Partitioned AS P
INNER JOIN Concatenated AS C
ON P.ID = C.ID
AND P.NameNumber = C.NameNumber + 1
)
SELECT
ID,
FullName
FROM Concatenated
WHERE NameNumber = NameCount
説明
このアプローチは、次の3つのステップに要約されます。
連結の必要に応じて、行に番号を付けOVER
、PARTITION
グループ化して順序付けします。結果はPartitioned
CTEです。後で結果をフィルタリングするために、各パーティションの行数を保持します。
再帰CTE(Concatenated
)を使用して、行番号(列)を反復処理し、列に値をNameNumber
追加します。Name
FullName
が最も高い結果を除くすべての結果を除外しますNameNumber
。
このクエリを予測可能にするには、グループ化(たとえば、シナリオでは同じ行ID
が連結される)と並べ替え(連結の前に文字列をアルファベット順に並べ替えるだけだと想定)の両方を定義する必要があることに注意してください。
次のデータを使用して、SQLServer2012でソリューションをすばやくテストしました。
INSERT dbo.SourceTable (ID, Name)
VALUES
(1, 'Matt'),
(1, 'Rocks'),
(2, 'Stylus'),
(3, 'Foo'),
(3, 'Bar'),
(3, 'Baz')
クエリ結果:
ID FullName
----------- ------------------------------
2 Stylus
3 Bar, Baz, Foo
1 Matt, Rocks