从大表中删除重复行

时间:2021-04-04 17:42:49

标签: sql sql-server

我从第三方获得数据并导入到 SQL 服务器。该表有 255,072,636 条记录,其中 61,714,772 条记录是唯一的。该表既没有特定的顺序,也没有任何索引。该表有 4 列:Field1(float), Field2(varchar(255), Field3(varchar(255), Field4(varchar(255)。我想根据已运行以下查询的 Field1 删除重复记录:

WITH CTE(Field1, Field2, Field3, Field4, DuplicateCount)
AS (SELECT *, 
           ROW_NUMBER() OVER(PARTITION BY Field1 ORDER BY Field1) AS DuplicateCount
    FROM MyTable)
DELETE FROM CTE
WHERE DuplicateCount > 1;

但是花了 13 个小时,然后我取消了它,上面提到的数字是在那之后。有没有更好的方法来删除重复项?

4 个答案:

答案 0 :(得分:2)

您可以将唯一行插入到临时表中,而不是删除,然后您可以重命名该表或在截断该表后将所需的行复制到原始表中。

在表格中插入唯一的行。

WITH CTE(Field1, Field2, Field3, Field4, DuplicateCount)
AS (SELECT *, 
           ROW_NUMBER() OVER(PARTITION BY Field1 ORDER BY Field1) AS DuplicateCount
    FROM MyTable)
select * into TempTable FROM CTE
WHERE DuplicateCount = 1;

然后,您可以像下面这样重命名该表:

drop table MyTable;
sp_rename 'temptable','MyTable';

或者将唯一的行复制回原始表:

Truncate table MyTable;
insert into MyTable select *from TempTable ;
drop table temptable;

答案 1 :(得分:1)

我会这样做:

  1. 在filed1 上建立索引(这需要几个小时)

    create ix_table on MyTable(files1) 
    
  2. 然后要么删除重复项,要么为唯一值创建一个新表,如果您只是插入到新表中,速度可能会快一点

SELECT Field1, Field2, Field3, Field4
from 
( select * , 
           ROW_NUMBER() OVER(PARTITION BY Field1 ORDER BY Field1) AS dups
  FROM MyTable
) tt
where dups = 1

但是如果你从原始表中删除,但是它会更慢,你已经在该表的 field1 上有一个索引,如果你以后需要使用该索引进行任何查询。所以从长远来看,保留原始表可能更有效

答案 2 :(得分:0)

只需重新创建表:

select distinct *
into new_t
from t;

我建议在执行此操作之前在 (field1, field2, field3, field4) 上添加索引。

或者对于一列唯一性:

select t.*
from (select t.*,
             row_number() over (partition by field1 order by (select null)) as seqnum
      from t
     ) t
where seqnum = 1;

为此,您需要 (field1) 上的索引。

如果您确实需要重新使用原始表的名称,请将其截断并从 new_t 重新插入或重命名该表。

答案 3 :(得分:0)

感谢“Kazi Mohammad Ali Nur”和“eshirvana”。我已经结合了那里的解决方案。起初,我在 Field1 上创建了索引。

CREATE CLUSTERED INDEX Index_Name   
    ON MyTable(Field1);

然后我执行以下查询将唯一记录插入新表并删除原始表。

WITH CTE(Field1, Field2, Field3, Field4, DuplicateCount)
AS (SELECT *, 
           ROW_NUMBER() OVER(PARTITION BY Field1 ORDER BY Field1) AS DuplicateCount
    FROM MyTable)
select * into TempTable FROM CTE
WHERE DuplicateCount = 1;

它奏效了。

谢谢大家。

相关问题