質問

永続的なデータが入ったテーブルがあります。これで照会すると、結果に必要な値を計算する非常に複雑なCTEもあり、欠落した行を永続的なテーブルに挿入する必要があります。最後に、CTEで識別されたすべての行で構成される結果を選択したいが、それらがすでにテーブルにある場合はテーブルからのデータを使用して、行が挿入されたかどうかにかかわらず情報が必要です。

これがこのように機能するのを簡素化しました(次のコードは、試してみたい場合は通常のクエリとして実行されます):

-- Set-up of test data, this would be the persisted table 
DECLARE @target TABLE (id int NOT NULL PRIMARY KEY) ;
INSERT INTO @target (id) SELECT v.id FROM (VALUES (1), (2)) v(id);

-- START OF THE CODE IN QUESTION
-- The result table variable (will be several columns in the end)
DECLARE @result TABLE (id int NOT NULL, new bit NOT NULL) ;

WITH Source AS (
    -- Imagine a fairly expensive, recursive CTE here
    SELECT * FROM (VALUES (1), (3)) AS Source (id)
)
MERGE INTO @target AS Target
    USING Source
    ON Target.id = Source.id
    -- Perform a no-op on the match to get the output record
    WHEN MATCHED THEN 
        UPDATE SET Target.id=Target.id
    WHEN NOT MATCHED BY TARGET THEN
        INSERT (id) VALUES (SOURCE.id)
    -- select the data to be returned - will be more columns
    OUTPUT source.id, CASE WHEN $action='INSERT' THEN CONVERT(bit, 1) ELSE CONVERT(bit, 0) END
      INTO @result ;

-- Select the result
SELECT * FROM @result;

私は好きではありません WHEN MATCHED THEN UPDATE パート、私は冗長な更新を残したいと思っていますが、その後、結果の行が得られません OUTPUT 句。

これは、この種の完成と返却を行うための最も効率的な方法ですか?

または、より効率的な解決策がないでしょうか MERGE, 、たとえば、結果を事前に計算することにより SELECT そして、実行します INSERT ある行の new=0?基本的に「クラスター化されたインデックスマージ」に要約されるため、クエリプランを解釈するのに苦労しています。 SELECT に続く INSERT 変異体。そして、SQL Server(Cu1を含む2008 R2)が実際にそれを見るのに十分賢いのだろうか UPDATE NO-OPです(例:書き込み不要)。

役に立ちましたか?

解決

ダミー変数を宣言し、その値をWhen Matched句に設定することができます。

 DECLARE @dummy int;
 ...
 MERGE
 ...
 WHEN MATCHED THEN
   UPDATE SET @dummy = 0
 ...

実際のテーブルアップデートよりも安価であるべきだと思います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top