重新分配重复的记录引用并删除冗余记录

Reallocate duplicate record references and remove redundant records

提问人:MG SQL Muppet 提问时间:9/13/2023 最后编辑:Thom AMG SQL Muppet 更新时间:9/14/2023 访问量:33

问:

我在表 1 中重复了数据。下面列出的字段中的所有信息必须相同才能被视为重复。该表还有其他列,但这些列无关紧要。唯一标识符为 PDS_Item_Ref。

PDS_Item_Ref 项目参考 年龄 生命 条件 评论 房 协 图片文件 立即的 DETAILS_REF
1830 32976 5 26 平均 无访问权限 0 0 16
1872 32976 5 26 平均 无访问权限 0 0 16
1900 32976 5 26 平均 无访问权限 0 0 16

这些记录使用PDS_Item_Ref列引用表 2 中的其他数据。可以引用部分或全部各种记录。

Collection_Ref PDS_Item_Ref 数量
1000 1830 3
1001 1872 5
1002 1900 6
1003 1830 6

我需要更新表 2 中的 PDS_Item_Ref 字段,以选择具有最低 [PDS_Item_Ref] 的重复项,然后删除表 1 中现在冗余的记录的其余部分。在上面的例子中,项目1830将被保留,所有其他项目将被删除。

sql sql-server sql-server-2012

评论

0赞 Thom A 9/13/2023
这些回答了你的问题吗?获取每个组的前 1 行 如何删除SQL Server中的重复行?

答:

0赞 siggemannen 9/13/2023 #1

这可以通过多种方式完成,我更喜欢使用三步模型:

  1. 将重复项放入临时表
  2. 更新引用的表
  3. 从主表中删除重复项
DROP TABLE #maintable
DROP TABLE #dupes
DROP TABLE #updatetable
SELECT  *
INTO #maintable
FROM    (
        VALUES  (1830, 32976, 5, 26, N'Average', N'No access', 0, N'NULL', 0, 16)
        ,   (1872, 32976, 5, 26, N'Average', N'No access', 0, N'NULL', 0, 16)
        ,   (1900, 32976, 5, 26, N'Average', N'No access', 0, N'NULL', 0, 16)
        ,   (1901, 32976, 5, 26, N'Average', N'Has access', 0, N'NULL', 0, 16)
    ) t (PDS_Item_Ref,ItemRef,Age,Life,Condition,Comments,HS,Picturefile,Immediate,DETAILS_REF)
    
SELECT  PDS_item_ref, min_ref
INTO #dupes
FROM    (
    SELECT  *
    ,   MIN(PDS_item_ref) OVER(partition BY ItemRef,Age,Life,Condition,Comments,HS,Picturefile,Immediate,DETAILS_REF ORDER BY pds_item_ref) AS min_ref
    FROM    #maintable
) x
WHERE   x.min_ref <> PDS_Item_Ref

-- create index...
CREATE UNIQUE CLUSTERED INDEX IX_#dupes ON  #dupes (PDS_item_ref)

SELECT  *
INTO #updatetable
FROM    (

    VALUES  (1000, 1830, 3)
    ,   (1001, 1872, 5)
    ,   (1002, 1900, 6)
    ,   (1003, 1830, 6)
) t (Collection_Ref,PDS_Item_Ref,Quantity)


-- update dups...
SET xact_abort ON;

BEGIN TRAN
    
    UPDATE  t
    SET PDS_Item_Ref = d.min_ref
    FROM    #updatetable t
    INNER JOIN #dupes d
        ON  d.PDS_item_ref = t.PDS_item_ref
    
    -- update others...
    
    -- Finally delete
    
    DELETE  t
    FROM    #maintable t
    INNER JOIN #dupes d
        ON  d.PDS_item_ref = t.PDS_Item_Ref

    SELECT  *
    FROM    #updatetable
    SELECT  *
    FROM    #maintable
COMMIT TRAN;

首先,我创建一些测试数据,然后获取所有重复的行。 是一个窗口聚合,设计用于两件事,即按所有列查找组并获取每个组的最小 ID。MIN(PDS_item_ref) OVER(partition BY ItemRef,Age,Life,Condition,Comments,HS,Picturefile,Immediate,DETAILS_REF ORDER BY pds_item_ref)

WHERE x.min_ref <> PDS_Item_Ref这样可以确保我们只获取组的重复行

最后,我们可以更新相关表并从主表中删除。在事务中做一些事情是个好主意,这样你就不会在出现问题时得到部分更新的数据。

最重要的是,在开始工作之前创建一个备份。

评论

0赞 MG SQL Muppet 9/13/2023
工作完美,谢谢,非常感谢您在这方面的时间和精力