1

たくさんのものを返すストアドプロシージャを実行したいと思います。そのうちの1つは、結果のコンマ区切りの文字列です。

COALESCEについて読み、次のようにする関数を作成しました。

DECLARE @ListOfStuff NVARCHAR(4000)

SELECT  @ListOfStuff = COALESCE(@ListOfStuff + ', ', '') + Z.SingleStuff
FROM    X 
INNER JOIN Y ON X.SomeId = Y.Id
INNER JOIN Z ON Y.SomeId = Z.id
WHERE --Some condition

RETURN ISNULL(@ListOfStuff, '')

そして、メインのSELECTでこの関数を呼び出すと、期待どおりに機能します。ただし、この手順は実行に非常に長い時間がかかり、タイムアウトになることがよくあります。私が疑問に思っているのは、誰かがそれを最適化する方法を知っているかどうかです。関数を削除し、このロジックをプロシージャに組み込むと、実行速度が大幅に向上すると思いますが、この方法でCOALESCEを使用するサブ選択を行う方法を見つけることができませんでした。

このロジックを最適化する方法はありますか?よろしくお願いします

4

3 に答える 3

2

@ListOfStuff を '' として宣言し、文字列の連結と最終的な戻り値を少し異なる方法で処理するだけで、COALESCE を完全に不要にすることができます。現状では、すべての行で評価しています。

DECLARE @ListOfStuff NVARCHAR(4000) = ''

SELECT  @ListOfStuff = @ListOfStuff + Z.SingleStuff + ','
FROM    X 
INNER JOIN Y ON X.SomeId = Y.Id
INNER JOIN Z ON Y.SomeId = Z.id
WHERE --Some condition

IF LEN(@ListOfStuff) > 0
BEGIN
    SELECT @ListOfStuff = LEFT(@ListOfStuff, LEN(@ListOfStuff) - 1)
END
RETURN @ListOfStuff

可能な最適化は、結合で使用されるすべての列にインデックスがあることを確認することです.nvarcharではなくvarcharを使用できる場合(もちろん、z.SingleStuffの内容とデータ型によって異なります)、少し役立つかもしれません. しかし、それを呼び出すストアド プロシージャを大幅に変更しなければ、他に何ができるかわかりません。

この関数が SELECT のすべての行に対して呼び出される場合、テーブル値関数または CROSS APPLY (使用方法と RDBMS によって異なります) のいずれかを使用すると、うまくいく可能性があります。

于 2012-05-01T21:19:53.547 に答える
0

COALESCEは、ここでは実際には作業を行っていません(nullを分類するだけです。http://msdn.microsoft.com/en-us/library/ms190349.aspxを参照してください) 。

値のコンマによる連結は、@ ListOfStuff変数を使用して行われ、それを行うための良い(唯一の?)方法のようです。つまり、関数を削除する場合でも、これを行う必要があります。ストアドプロシージャで。関数を持っていること自体が、あなたが見ているパフォーマンスの低下をもたらすべきではありません。

したがって、結合列(id、SomeId)にインデックスが付けられるようにする以外に、これを最適化できるかどうかはわかりません。

于 2012-05-01T21:00:55.033 に答える
0

SP を見ないと、実際の実用的なソリューションを提案できませんが、SQL-Server を使用している場合はFOR XML PATH、SO に関する多くの質問で取り上げられているアプローチを使用できます。私は最近、このアプローチの背後にあるロジックを分解する質問に答えまし。関数は SQL の好ましいセットベースのアプローチから離れているため、私は関数アプローチよりもこれを好みます。

KMは、こちらのより良い解決策へのリンクを使用して、私のアプローチの欠陥を指摘しました。同じロジックが引き続き適用されますが、KM は連結するテキスト内に表示される予約文字の問題を回避しました。

あなたが探している解決策についての私の最善の推測は次のとおりです。

SELECT  X.SomeColumn,
        Y.SomeColumn,
        STUFF(( SELECT  ', ' + Z.SingleStuff
                FROM    Z
                WHERE   Z.ID = Y.SomeID
                FOR XML PATH(''), TYPE
            ).Value('.', 'VARCHAR(MAX)'), 1, 2, '') [ListOfStuff]
FROM    X 
        INNER JOIN Y 
            ON X.SomeId = Y.Id
WHERE --Some condition
于 2012-05-03T09:56:34.960 に答える