web-dev-qa-db-ja.com

SQL ServerMERGEステートメントに関する問題

ソーステーブル

Id, Name, Address
1   A     #202
1   A     #203
1   A     #204
2   A     #202

ターゲットテーブル

Id, Name, Address
1   A     NULL

マージ後

Id, Name, Address
1   A     #202
2   A     #202

私はこのSQLを使用しています

create table #S   (ID int, Name varchar(25) NULL, Address varchar(25) NULL)
create table #T   (ID int, Name varchar(25) NULL, Address varchar(25) NULL)

 INSERT #S values(1, 'A', '#202')
 INSERT #S values(1, 'A', '#203')
 INSERT #S values(1, 'A', '#203')
 INSERT #S values(1, 'A', '#204')

 INSERT #T values(1, 'A', NULL)

 MERGE #T USING
  (
Select id, name, address 
from #S
  ) AS S(id,name,address)
 on #T.id=S.id and #T.Name=S.Name
 when not matched THEN
    INSERT values(S.id,S.Name, S.Address)
 when matched then
    update set Address = S.Address;
 GO 

 Select * from #T
 GO 

 Select * from #S
 GO 

これによりエラーが発生します

メッセージ8672、レベル16、状態1、行18
MERGEステートメントが同じ行を複数回更新または削除しようとしました。これは、ターゲット行が複数のソース行と一致する場合に発生します。 MERGEステートメントは、ターゲットテーブルの同じ行を複数回更新/削除することはできません。 ON句を調整して、ターゲット行が最大で1つのソース行と一致するようにするか、GROUPBY句を使用してソース行をグループ化します。

Aの行を、一致する3つの値のいずれかからのアドレス値で更新したいと思います。これを行う方法?

18
R.D

_#S_の4つの値のいずれかが、ターゲットテーブルの単一行の値と一致します(#Sのすべての値はid = 1およびname = 'A'であるため、すべてターゲットの単一行と一致します)。値は4回更新されます-それはエラーが言うことであり、それは絶対に正しいです。

ここで本当に達成したいことは何ですか?

アドレスをソーステーブルの最初の値に設定しますか?副選択で_TOP 1_句を使用します。

_MERGE #T 
USING (SELECT TOP 1 id, name, address FROM #S) AS S
ON #T.id = S.id AND #T.Name = S.Name
WHEN NOT MATCHED THEN
    INSERT VALUES(S.id,S.Name, S.Address)
WHEN MATCHED THEN
    UPDATE SET Address = S.Address;
_

アドレスをソーステーブルの値のランダムな要素に設定しますか?副選択で_TOP 1_およびORDER BY NEWID()句を使用します。

_MERGE #T 
USING (SELECT TOP 1 id, name, address FROM #S ORDER BY NEWID()) AS S
ON #T.id = S.id AND #T.Name = S.Name
WHEN NOT MATCHED THEN
    INSERT VALUES(S.id,S.Name, S.Address)
WHEN MATCHED THEN
    UPDATE SET Address = S.Address;
_

4つのソース行を1つのターゲット行に一致させると、有用な結果が得られることはありません。本当に必要なものを知る必要があります。

マーク

24
marc_s

を使用して重複を削除します

select R.* 
from  (SELECT Customer,Material,Received_date_time,
row_number() over (Partition by Customer, Material   
order by  Customer,Material,Received_date_time) as rn
      from Customer_Table WHERE Status=0     
     ) as R
where R.rn = 1

マージの場合、重複することはできないため、常に最新のものを取得する必要があります

1