1

これは、更新する必要があるテーブルです。

TABLE A
-------------------
ID   UserID   Value
-------------------
1    1        1A
2    1        1B
3    1        1C
4    2        2A
5    3        3A
6    4        4A

更新されたユーザーの新しい値を含む一時テーブルがあります。

TEMP TABLE
-------------
UserID  Value
-------------
1   1A         --existing
1   1D         --new
2   2B         --new

TEMP TABLE の新しい値を反映するように TABLE A を更新する方法を知りたいです。期待される結果は次のようになります。

TABLE A
-------------------
ID   UserID   Value
-------------------
1    1        1A
7    1        1D
8    2        2B
5    3        3A
6    4        4A

私が持っている2つのアイデアは次のとおりです。

  • 削除してから挿入します。左結合を使用して存在しなくなった値を特定し、それらを削除します。次に、右結合を使用して新しい値を決定し、それらを挿入します。
  • MERGEを使用できるかもしれませんが、実装方法はよくわかります。

テスト環境

IF OBJECT_ID('tempdb..#tableA') IS NOT NULL
BEGIN
    DROP TABLE #tableA
END

IF OBJECT_ID('tempdb..#tempTable') IS NOT NULL
BEGIN
    DROP TABLE #tempTable
END

CREATE TABLE #tableA
(
    ID int identity(1,1),
    UserID int,
    Value nvarchar(50)
)

CREATE TABLE #tempTable
(
    UserID int,
    Value nvarchar(50)
)

INSERT INTO #tableA([UserID], [Value])
VALUES (1, '1A'),
(1, '1B'),
(1, '1C'),
(2, '2A'),
(3, '3A'),
(4, '4A')

INSERT INTO #tempTable([UserID], [Value])
VALUES (1, '1A'),
(1, '1D'),
(2, '2B')

SELECT * FROM #tableA
SELECT * FROM #tempTable

編集:次のソリューションは、テーブル A から ID (1,2,3,4) を削除しますが、(2,3,4) だけを削除したいです。これは、ID 1 が既に TABLE A に存在し、削除して再度挿入する必要がないためです。

Delete 
From    TableA  A
Where Exists
(
    Select  *
    From    TempTable   T
    Where   T.UserId = A.UserId
)

解決策はありますが、かなり面倒です。それを改善する方法はありますか?

-- This will get the IDS (1,2,3,4) from TABLE A
SELECT * INTO #temp1 FROM #tableA
WHERE EXISTS
(
    Select *
    From #tempTable T
    Where T.UserId = #tableA.UserId
)

--This will get the ID (1) from TABLE A. I do not want this deleted.
SELECT * INTO #temp2 FROM #tableA
WHERE EXISTS
(
    Select *
    From #tempTable T
    Where T.UserId = #tableA.UserId AND T.[Value]=#tableA.Value
)

--LEFT JOIN to only delete the IDS (2,3,4)
DELETE FROM #tableA
WHERE EXISTS
(
    SELECT *
    FROM #temp1 a LEFT JOIN #temp2 b
    ON a.UserID=b.UserID AND a.Value=b.Value
    WHERE b.UserID IS NULL AND b.Value IS NULL
)
4

2 に答える 2

2

一時テーブルに表示されないレコードを削除したいので、削除/挿入メソッドを使用します。

Delete 
From    TableA  A
Where Exists
(
    Select  *
    From    TempTable   T
    Where   T.UserId = A.UserId
)

Insert
Into    TableA
        (UserId, Value)
Select  T.UserId, T.Value
From    TempTable   T
Where Not Exists
(
    Select  *
    From    TableA  A
    Where   A.UserId = T.UserId
    And     A.Value = T.Value
)

Outer Joinこれらのメソッドも使用できます。

Delete  A
From    TableA      A
Join    TempTable   T   On  T.UserId = A.UserId

Insert
Into        TableA
            (UserId, Value)
Select      T.UserId, T.Value
From        TempTable   T
Left Join   TableA      A   On  A.UserId = T.UserId
                            And A.Value = T.Value
Where       A.UserId Is Null

個人的にはRight Joins頭が痛いので、順番は自由に変えてください。

于 2015-01-21T19:33:04.310 に答える
2
--This will remove all records which have at least one row with a matching UserID in tempTable and which don't have a row that matches on both UserID and Value.
DELETE
  TableA  A
WHERE 
 A.UserID IN (SELECT DISTINCT USerID FROM TempTable)
AND NOT EXISTS
(
    Select  1
    From    TempTable   T
    Where   T.UserId = A.UserId
    AND     T.Value= A.Value
)
--This will add any rows from temptable that don't have a match already in TableA
INSERT INTO TableA(UserId, Value)
SELECT DISTINCT UserID,Value
FROM TempTable T
WHERE NOT EXISTS (SELECT 1 FROM TableA A 
WHERE T.UserID=A.UserID
AND T.value=A.Value)

これにより、必要な結果が得られます。それが巨大な結果セットである場合 (実際にははるかに広いテーブルまたは数百万行の場合)、パフォーマンスに影響する可能性があり、後退が必要になる場合があります。そうでなければ、トリックを行います

于 2015-01-21T20:48:30.360 に答える