我如何删除重复的行?

从相当大的SQL Server表中删除重复行的最佳方法是什么(即300,000多行)?

由于RowID标识字段的存在,行当然不会是完美的重复项。

MyTable的

RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null

假设没有空值, GROUP BY唯一列,并SELECT MIN (or MAX) RowId作为要保留的行。 然后,删除没有行ID的所有东西:

DELETE FROM MyTable
LEFT OUTER JOIN (
   SELECT MIN(RowId) as RowId, Col1, Col2, Col3 
   FROM MyTable 
   GROUP BY Col1, Col2, Col3
) as KeepRows ON
   MyTable.RowId = KeepRows.RowId
WHERE
   KeepRows.RowId IS NULL

如果你有一个GUID而不是一个整数,你可以替换

MIN(RowId)

CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn)))

另一种可能的方式是

; 

--Ensure that any immediately preceding statement is terminated with a semicolon above
WITH cte
     AS (SELECT ROW_NUMBER() OVER (PARTITION BY Col1, Col2, Col3 
                                       ORDER BY ( SELECT 0)) RN
         FROM   #MyTable)
DELETE FROM cte
WHERE  RN > 1;

我正在使用上面的ORDER BY (SELECT 0) ,因为它是任意的,在发生平局时要保留哪一行。

例如,要使用RowID顺序保留最新的一个,可以使用ORDER BY RowID DESC

执行计划

执行计划通常比接受的答案更简单,更高效,因为它不需要自加入。

执行计划

但情况并非总是如此。 GROUP BY解决方案可能更GROUP BY一个地方是散列聚合将优先于流聚合而被选择的情况。

ROW_NUMBER解决方案将始终提供几乎相同的计划,而GROUP BY策略则更加灵活。

执行计划

可能有利于哈希聚合方法的因素是

  • 在分区列上没有有用的索引
  • 每个组中相对较少的组相对较多的重复
  • 在第二种情况下极端版本(如果有在每个很多重复极少数群体)一个也考虑简单地插入的行保持到一个新表,然后TRUNCATE -ing原件和复制回相比,删除,以减少日志记录这些行的比例非常高。


    有一篇关于删除Microsoft支持网站上的重复内容的好文章。 这是非常保守的 - 他们让你在单独的步骤中做所有事情 - 但它应该可以很好地对付大型表格。

    过去我使用自连接来完成这个任务,但它可能会被HAVING子句弄糟:

    DELETE dupes
    FROM MyTable dupes, MyTable fullTable
    WHERE dupes.dupField = fullTable.dupField 
    AND dupes.secondDupField = fullTable.secondDupField 
    AND dupes.uniqueField > fullTable.uniqueField
    
    链接地址: http://www.djcxy.com/p/4215.html

    上一篇: How can I remove duplicate rows?

    下一篇: Android error: Failed to install *.apk on device *: timeout