如何使用 SQL Server 中另一个表中的数据更新数据库表以删除重复项?

问题描述 投票:0回答:2

我正在尝试执行我认为相当复杂的更新语句,并且解决方案感觉超出了我的掌握范围。无论如何,请考虑以下两个表。 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 语句中执行此操作。

sql sql-server aggregate-functions
2个回答
0
投票

我记得一个类似的问题,不确定它是否重复,但看起来您正在尝试更新 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;

0
投票

如何使用 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;
© www.soinside.com 2019 - 2024. All rights reserved.