web-dev-qa-db-ja.com

CONCATテキストへのCTEクエリ(10,000行以上)

データの行をループし、テキストをそれぞれSampleUserNumberの1行に連結するCTEクエリを作成しようとしています。

以下は私が取り組んでいるものです:

CREATE TABLE #SampleTable
(
SampleRowID INT IDENTITY(1,1),
SampleUserNumber INT,
SampleLineNumber INT,
SampleTextLine VARCHAR(1000)
)

Sample Data

これが私のCTEクエリです:

CTE Query

これが出力です:

Result

CTEクエリは機能し、結果は正しいですが、私の主な問題は、パフォーマンスと処理する必要があるレコードの量です。現在、最低でも10万件のレコードを扱っています。

質問:

  1. 100,000レコードを処理するようにクエリを誤って記述しましたか? CTEを書くためのより効率的な方法はありますか?

  2. これを行うためのより効率的でより良い方法はありますか? [他に方法がない限り、ループは問題外です]

すべての画像でごめんなさい。ここに書き出すより、すべてを表示する方がはるかに簡単だと思いました。

ありがとうございました。

2
HelloWorld2099

このアプローチは比較してどのように機能しますか?

SELECT 
  SampleUserNumber, 
  CombinedMessage = STUFF(
    (SELECT N' ' + SampleTextLine FROM #SampleTable
       WHERE SampleUserNumber = t.SampleUserNumber
       ORDER BY SampleLineNumber
       FOR XML PATH, TYPE).value(N'.[1]',N'nvarchar(max)'),1,1,'')
FROM #SampleTable AS t
GROUP BY SampleUserNumber
ORDER BY SampleUserNumber;

#tempテーブルがSampleUserNumber, SampleLineNumberにクラスター化インデックスを持っているか、少なくともINCLUDEs SampleTextLineの2つの列にクラスター化されていないインデックスがあると便利でしょう。

SQL Server 2017では、はるかに簡単なアプローチを使用でき、ほぼ高速であることが保証されています。

SELECT SampleUserNumber, 
  CombinedMessage = STRING_AGG(CONVERT(varchar(max),SampleTextLine), ' ') 
                    WITHIN GROUP (ORDER BY SampleLineNumber)
FROM #SampleTable
GROUP BY SampleUserNumber 
ORDER BY SampleUserNumber;

CONVERTを回避するには、#tempテーブル列をMAXタイプにするだけです。

1
Aaron Bertrand