12

プレースホルダー付きのテキスト フィールドを含むテーブルがあります。このようなもの:

Row Notes  
1.  This is some notes ##placeholder130## this ##myPlaceholder##, #oneMore#. End.
2.  Second row...just a ##test#.   

(このテーブルには、平均で約 1 ~ 5,000 行が含まれています。1 行のプレースホルダーの平均数は 5 ~ 15 です)。

これで、次のようなルックアップ テーブルができました。

Name             Value
placeholder130    Dog
myPlaceholder     Cat
oneMore           Cow
test              Horse   

(ルックアップ テーブルには、10k から 100k のレコードが含まれます)

これらのプレースホルダーを文字列からルックアップ テーブルに結合し、値に置き換える最速の方法を見つける必要があります。したがって、私の結果は次のようになります(1行目):

これは犬、この猫、牛です。終わり。

私が思いついたのは、各行をプレースホルダーごとに複数に分割し、それをルックアップ テーブルに結合してから、レコードを新しい値で元の行に連結することでしたが、平均で約 10 ~ 30 秒かかります。

4

7 に答える 7

4

これを試して

;WITH CTE (org, calc, [Notes], [level]) AS
(
    SELECT [Notes], [Notes], CONVERT(varchar(MAX),[Notes]), 0 FROM PlaceholderTable

    UNION ALL

    SELECT  CTE.org, CTE.[Notes],
        CONVERT(varchar(MAX), REPLACE(CTE.[Notes],'##' + T.[Name] + '##', T.[Value])), CTE.[level] + 1
    FROM    CTE
    INNER JOIN LookupTable T ON CTE.[Notes] LIKE '%##' + T.[Name] + '##%'

)

SELECT DISTINCT org, [Notes], level FROM CTE
WHERE [level] = (SELECT MAX(level) FROM CTE c WHERE CTE.org = c.org)

SQL フィドルのデモ

以下のdevioblog投稿を参照してください

Devioブログ投稿

于 2013-07-05T11:12:01.040 に答える
1

速度を上げるために、メモ テンプレートを前処理してより効率的な形式にすることができます。これはフラグメントのシーケンスで、それぞれが置換で終わります。最後のフラグメントの置換は NULL である可能性があります。

Notes
Id     FragSeq    Text                    SubsId
1      1          'This is some notes '   1
1      2          ' this '                2
1      3          ', '                    3
1      4          '. End.'                null
2      1          'Second row...just a '  4
2      2          '.'                     null

Subs
Id  Name               Value
1   'placeholder130'   'Dog'
2   'myPlaceholder'    'Cat'
3   'oneMore'          'Cow'
4   'test'             'Horse'  

これで、単純な結合で置換を行うことができます。

SELECT Notes.Text + COALESCE(Subs.Value, '') 
FROM Notes LEFT JOIN Subs 
ON SubsId = Subs.Id WHERE Notes.Id = ?
ORDER BY FragSeq

これにより、置換が完了したフラグメントのリストが生成されます。私は MSQL ユーザーではありませんが、SQL のほとんどの方言では、これらのフラグメントを変数に簡単に連結できます。

DECLARE @Note VARCHAR(8000)
SELECT @Note = COALESCE(@Note, '') + Notes.Text + COALSCE(Subs.Value, '') 
FROM Notes LEFT JOIN Subs 
ON SubsId = Subs.Id WHERE Notes.Id = ?
ORDER BY FragSeq

メモ テンプレートをフラグメントに前処理することは、他の投稿の文字列分割手法を使用して簡単に行うことができます。

残念ながら、私はこれをテストできる場所にいませんが、問題なく動作するはずです。

于 2013-07-10T20:20:51.073 に答える
0

10k以上のルックアップでどのように機能するかは本当にわかりません。古い動的 SQL はどのように機能しますか?

DECLARE @sqlCommand  NVARCHAR(MAX)
SELECT @sqlCommand  = N'PlaceholderTable.[Notes]'

SELECT @sqlCommand  = 'REPLACE( ' + @sqlCommand  + 
                      ', ''##' + LookupTable.[Name] + '##'', ''' + 
                      LookupTable.[Value] + ''')'  
FROM LookupTable

SELECT @sqlCommand  = 'SELECT *, ' + @sqlCommand  + ' FROM PlaceholderTable'

EXECUTE sp_executesql @sqlCommand

フィドルのデモ

于 2013-07-05T16:34:37.393 に答える