【问题标题】:Tables joins to get result表连接以获得结果
【发布时间】:2015-01-21 19:21:30
【问题描述】:

这是需要更新的表。

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

我想知道如何更新 TABLE A 以反映 TEMP TABLE 中的新值。预期的结果是:

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

我有两个想法:

  • 先删除再插入。使用左连接确定哪些值不再存在,然后将其删除。然后使用右连接确定哪些值是新值,然后插入它们。
  • 也许我可以使用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
)

【问题讨论】:

    标签: sql sql-server tsql sql-merge


    【解决方案1】:
    --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)
    

    这会得到你想要的结果。如果它是一个巨大的结果集 - 无论是现实生活中更宽的表还是数百万行,那么可能会影响性能,需要后退一步。否则,会成功的

    【讨论】:

      【解决方案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 只是伤了我的脑筋,所以请随意更改顺序。

      【讨论】:

      • 我喜欢您对 EXISTS 的使用,但是您的解决方案与我的预期结果不符。在这两个示例中,用户 ID 3 和 4 都被删除,这是我不希望发生的。基本上,临时表应该只删除/插入表中指定的用户 ID。我该如何解决这个问题?
      • 谢谢,快到了。你能看看我添加到我的 OP 底部的查询,它解释了缺少的内容。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-05
      • 2015-12-04
      相关资源
      最近更新 更多