Sql-Server

合併行,然後從另一個表更新 fk 以匹配新值

  • November 2, 2016

我有 2 個表 tb1 (id, name, record_no, location,…) tb2(id, test, date,…)

Tb1 在 tb1.id = tb2.id 上連接到 tb2

問題是 TB1 具有重複的條目,這些條目具有新的 ID。對於每個唯一條目,我需要將這些 id 合併為一個 1,然後更新 tb2.id 以匹配更改。

不確定無需手動更新每一行的最有效方法。

SELECT * FROM TB1

ID, NAME,    DOB,        RECORD_NUM
1, John Doe, 01/01/1900, 123456789
2, John Doe, 01/01/1900, 123456789
3, Jane Doe, 11/03/2016, 294018400
4, Jane Doe, 11/03/2016, 294018400
...

SELECT * FROM TB2

ID, Test,    Result, Date
1,  English, Pass,   01/01/1900
1,  Grammer, Fail,   01/02/1900
2,  Gym,     Pass,   01/01/1900
3,  Art,     Pass,   11/02/2016
4,  Gym,     Pass,   11/03/2016
...

基本上我需要獲取行 ID 2 並將其從 TB1 合併為 ID 1,然後 2 出現在 TB2 中我需要將其更新為 1。

我知道條目通常與 Record_num 相同,或者如果這是一個空值,我可以使用名稱和 dob(因為它們在集合中應該是唯一的)。

SELECT * FROM TB1

ID, NAME,    DOB,        RECORD_NUM
1, John Doe, 01/01/1900, 123456789
3, Jane Doe, 11/03/2016, 294018400
...

SELECT * FROM TB2

ID, Test,    Result, Date
1,  English, Pass,   01/01/1900
1,  Grammer, Fail,   01/02/1900
1,  Gym,     Pass,   01/01/1900
3,  Art,     Pass,   11/02/2016
3,  Gym,     Pass,   11/03/2016
...

我希望這有助於解釋更多。

您可以先更新第二個表,然後從第一個表中刪除重複的(現在未引用的)行。

(PARTITION BY name, dob, record_num)是將行標識為重複項的內容。如果需要辨識更多或更少的列,請進行相應調整。

如果其他會話訪問該表,最好將這兩個語句放在一個事務中以避免奇怪的影響/錯誤(在 2 個語句之間插入新行或刪除可能導致第二個語句失敗或最後有未引用的行:

WITH ids AS
( SELECT dup_id = id,
        good_id = MIN(id) OVER (PARTITION BY name, dob, record_num) 
 FROM tb1 
) 
UPDATE t2
SET t2.id = i.good_id
FROM tb2 AS t2 
 JOIN ids AS i
   ON i.dup_id = t2.id
WHERE i.dup_id <> i.good_id ;


WITH ids AS
( SELECT dup_id = id,
        good_id = MIN(id) OVER (PARTITION BY name, dob, record_num) 
 FROM tb1 
) 
DELETE d
FROM tb1 AS d
 JOIN ids AS i
   ON i.dup_id = d.id
WHERE i.dup_id <> i.good_id ; 

測試了一個rextester.com


第二條語句本來可以寫得更簡單,但我發現上面的第一種方式更具可讀性,因為這兩條語句具有幾乎相同的FROMandWHERE子句。

DELETE i
FROM 
     ( SELECT dup_id = id,
              good_id = MIN(id) OVER (PARTITION BY name, dob, record_num) 
       FROM tb1 
     )               -- the ids CTE rewritten as a derived table
     AS i
WHERE i.dup_id <> i.good_id ; 

引用自:https://dba.stackexchange.com/questions/154085