我正在尝试执行我认为相当复杂的更新语句,并且解决方案感觉超出了我的掌握范围。无论如何,请考虑以下两个表。 Val1、Val2 和 Val3 组合起来形成唯一的代码。然后将它们绑定到另一个表中的“Items”(此处未描述,仅由 ItemId 引用)。最后,另一个表引用了 Table1 唯一代码以及项目。
表1
身份证 | 商品编号 | Val1 | Val2 | Val3 |
---|---|---|---|---|
1 | 2 | 啊啊 | bb | 100 |
2 | 2 | 啊啊 | bb | 100 |
3 | 2 | ccc | dd | 222 |
4 | 2 | ccc | dd | 222 |
5 | 3 | gg | 呵呵 | 100 |
表2
身份证 | 商品编号 | 表1.Id |
---|---|---|
100 | 2 | 1 |
101 | 2 | 2 |
102 | 2 | 3 |
103 | 2 | 4 |
发生的情况是,通过自动导入过程将重复项插入到 Table1 中。此后,我更新了导入过程,不再插入重复项,但我需要清理现有数据。
我有一个查询要删除 Table1 中的重复值,但由于 Table2 上的外键关系,我无法简单地运行它。
因此,我需要做的是使用 Table1 中的正确 ID 更新 Table2 中的 Table1.Id 列,然后我可以单独运行查询以删除重复项(从 Table1 中)。
我有类似以下内容:
update Table2
set Table1.Id = (
select ID
from Table1
where ID in (
select max(ID)
from Table1
group by ItemId, Va1, Val2, Val3
having count(*) > 1
)
--and ItemId = 2 --added for testing
)
where Table1.ID in (
select id
from Table1
where id not in (
select max(id)
from Table1
group by ItemId, Va1, Val2, Val3
)
--and ItemId = 2 --added for testing
)
因此,实际上,我希望将 Table2 中的第 100 行将 Table1.Id 设置为 2,将第 102 行将 Table1.Id 设置为 4。
那么Table1中的第1行和第3行将不再在Table2中被引用,因此可以被删除。
如您所见,我可以针对简单(或特定)的示例执行此操作。然而,我正在努力将其通用化,以便它能够处理多个 id 和所有情况。注意:最终将会发生数千次更新。
我可以循环访问结果集,我只是想要一种巧妙的方法在单个 Update 语句中执行此操作。
我记得一个类似的问题,不确定它是否重复,但看起来您正在尝试更新 Table2 以在从 Table1 中删除重复项后正确引用 Table1 中的唯一行。 Yu 可以尝试在单个语句中更新 Table2 以引用 Table1 中的正确 ID
-- Update Table2 to reference correct Table1 IDs
WITH CTE AS (
-- Identify the correct IDs from Table1 for each group of duplicates
SELECT
MAX(ID) AS CorrectID,
ItemId,
Val1,
Val2,
Val3
FROM Table1
GROUP BY ItemId, Val1, Val2, Val3
HAVING COUNT(*) > 1
)
UPDATE t2
SET t2.Table1_Id = c.CorrectID
FROM Table2 t2
JOIN CTE c ON t2.ItemId = c.ItemId
AND t2.Table1_Id IN (SELECT ID FROM Table1 WHERE ItemId = c.ItemId AND Val1 = c.Val1 AND Val2 = c.Val2 AND Val3 = c.Val3);
-- Optional: Delete duplicates from Table1
DELETE t1
FROM Table1 t1
JOIN (
SELECT ID
FROM Table1
GROUP BY ItemId, Val1, Val2, Val3
HAVING COUNT(*) > 1
) dup ON t1.ID = dup.ID;
如何使用 min over parion by 作为您的 cte 进行更新。 这是小提琴。 https://dbfiddle.uk/RKUjhvB1
WITH MinIDCTE AS (
SELECT ID,
ItemId,
Val1,
Val2,
MIN(ID) OVER (PARTITION BY ItemId, Val1, Val2) AS MinID
FROM Table1
)
UPDATE t2
SET t2.Table1_Id = m.MinID
FROM Table2 t2
JOIN MinIDCTE m ON t2.Table1_Id = m.ID;