テーブルにアップサートを実行するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/19089

  •  09-06-2019
  •  | 
  •  

質問

ビューには、ジョブのリストがあり、そのジョブの担当者や現在のステージなどのデータが含まれています。各ステージで各人が持つジョブの数を返すストアド プロシージャを作成する必要があります。

これまでのところ、私はこれを持っています(簡略化):

DECLARE @ResultTable table 
(
  StaffName nvarchar(100),
  Stage1Count int,
  Stage2Count int
)

INSERT INTO @ResultTable (StaffName, Stage1Count)
  SELECT StaffName, COUNT(*) FROM ViewJob
  WHERE InStage1 = 1
  GROUP BY StaffName

INSERT INTO @ResultTable (StaffName, Stage2Count)
  SELECT StaffName, COUNT(*) FROM ViewJob
  WHERE InStage2 = 1
  GROUP BY StaffName

問題は、行が結合しないことです。したがって、スタッフ メンバーがステージ 1 とステージ 2 でジョブを持っている場合、@ResultTable には 2 つの行が存在します。私が本当にやりたいのは、スタッフメンバーの行が存在する場合はその行を更新し、存在しない場合は新しい行を挿入することです。

誰かがこれを行う方法を知っていますか、または別のアプローチを提案できますか?ユーザーのリストを反復処理するためにカーソルを使用することは絶対に避けたいと思っています (ただし、これは私の代替オプションです)。

SQL Server 2005 を使用しています。

編集:@リー: 残念ながら、InStage1 = 1 は単純化されたものです。実際には、WHERE DateStarted IS NOT NULL と DateFinished IS NULL に似ています。

編集:@BCS: 最初にすべてのスタッフを挿入するというアイデアが気に入っているので、毎回更新するだけで済みます。しかし、これらの UPDATE ステートメントを正しくするのに苦労しています。

役に立ちましたか?

解決

IIRC には、行が存在する場合に更新できる、ある種の「重複時」(名前が間違っている可能性があります) 構文があります (MySQL)

あるいは、次のような形式もあります。

INSERT INTO @ResultTable (StaffName, Stage1Count, Stage2Count)
  SELECT StaffName,0,0 FROM ViewJob
  GROUP BY StaffName

UPDATE @ResultTable Stage1Count= (
  SELECT COUNT(*) AS count FROM ViewJob
  WHERE InStage1 = 1
  @ResultTable.StaffName = StaffName)

UPDATE @ResultTable Stage2Count= (
  SELECT COUNT(*) AS count FROM ViewJob
  WHERE InStage2 = 1
  @ResultTable.StaffName = StaffName)

他のヒント

実際のところ、あなたはそれを実際よりもはるかに困難にしていると思います。このコードはあなたがやろうとしていることに対して機能しないでしょうか?

SELECT StaffName, SUM(InStage1) AS 'JobsAtStage1', SUM(InStage2) AS 'JobsAtStage2'
  FROM ViewJob
GROUP BY StaffName

存在するかどうかを確認して、適切なコマンドを使用するだけです。これは実際に舞台裏でカーソルを使用していると思いますが、おそらく得られる最高のものです。

IF (EXISTS (SELECT * FROM MyTable WHERE StaffName = @StaffName))
begin
    UPDATE MyTable SET ... WHERE StaffName = @StaffName
end
else
begin
    INSERT MyTable ...
end 

SQL2008 には新しい MERGE 機能があり、これは優れていますが、2005 にはありません。

実際の「更新/挿入」タイプのクエリを取得するには、ifexists... を使用する必要があります。これは残念ながらカーソルを使用することを意味します。

ただし、2 つのクエリを実行できます。1 つは既存の行が存在する場所で更新を実行し、その後新しい行を挿入します。少数の行のみを扱う場合を除き、このセットベースのアプローチの方が望ましいと思います。

結果テーブルに対する次のクエリでは、行が再度結合されます。これは、InStage1 と InStage2 が両方とも「1」になることは決してないことを前提としています。

select distinct(rt1.StaffName), rt2.Stage1Count, rt3.Stage2Count
from @ResultTable rt1
left join @ResultTable rt2 on rt1.StaffName=rt2.StaffName and rt2.Stage1Count is not null
left join @ResultTable rt3 on rt1.StaffName=rt2.StaffName and rt3.Stage2Count is not null

BCSの回答のバリエーションを使用してなんとか動作させることができました。ただし、テーブル変数は使用できないため、一時テーブルを作成する必要がありました。

CREATE TABLE #ResultTable
(
  StaffName nvarchar(100),
  Stage1Count int,
  Stage2Count int
)

INSERT INTO #ResultTable (StaffName)
  SELECT StaffName FROM ViewJob
  GROUP BY StaffName

UPDATE #ResultTable SET 
  Stage1Count= (
    SELECT COUNT(*) FROM ViewJob V
    WHERE InStage1 = 1 AND 
        V.StaffName = @ResultTable.StaffName COLLATE Latin1_General_CI_AS
    GROUP BY V.StaffName),
  Stage2Count= (
    SELECT COUNT(*) FROM ViewJob V
    WHERE InStage2 = 1 AND 
        V.StaffName = @ResultTable.StaffName COLLATE Latin1_General_CI_AS
    GROUP BY V.StaffName)

SELECT StaffName, Stage1Count, Stage2Count FROM #ResultTable

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