2013-08-24 47 views
4

我知道这个主题在此之前出现过很多次,但是没有一个建议的解决方案适用于我的数据集,因为我的笔记本电脑由于内存问题或完全存储而停止计算。从大型数据集(> 100Mio行)中删除重复信息

我的表如下所示,具有108宇行:

Col1  |Col2 | Col3   |Col4 |SICComb | NameComb 

Case New |3523 | Alexander  |6799 |67993523| AlexanderCase New 
Case New |3523 | Undisclosed |6799 |67993523| Case NewUndisclosed 
Undisclosed|6799 | Case New  |3523 |67993523| Case NewUndisclosed 
Case New |3523 | Undisclosed |6799 |67993523| Case NewUndisclosed 
SmartCard |3674 | NEC   |7373 |73733674| NECSmartCard 
SmartCard |3674 | Virtual NetComm|7373 |73733674| SmartCardVirtual NetComm 
SmartCard |3674 | NEC   |7373 |73733674| NECSmartCard 

独特的列是SICCombNameComb。我试着添加一个主键具有:

ALTER TABLE dbo.test ADD ID INT IDENTITY(1,1) 

但整数只是在一个新分钟填补了超过30 GB我的存储的。

哪个会是最快最有效的方法从表中删除重复项?

+0

@ user2713440你对重复的定义是什么?当所有列都相同时?或者当SICComb和NameComb相同? –

+0

当SICComb和NameComb都相同时。 – user2713440

+0

那么你如何决定要保留哪些? – Paparazzi

回答

2

一般情况下,从表中删除重复的最快方法是插入记录 - 没有重复 - 到一个临时表,截断原始表并插入它们放回

这里的想法,使用SQL Server语法:

select distinct t.* 
into #temptable 
from t; 

truncate table t; 

insert into t 
    select tt.* 
    from #temptable; 

当然,这在很大程度上取决于第一步的速度。而且,您需要有空间来存储同一张表的两个副本。

请注意,创建临时表的语法在数据库中各不相同。有些使用create table as而不是select into的语法。

编辑:

您的身份插入错误是麻烦的。我认为你需要从清单的列表中删除标识。或者做:

select min(<identity col>), <all other columns> 
from t 
group by <all other columns> 

如果你有一个标识列,那么没有重复(根据定义)。

最后,您需要决定您想要的行的编号。如果你能生成行一个新的ID,然后就离开了标识列出列清单的插入:

insert into t(<all other columns>) 
    select <all other columns>; 

如果需要旧的标识值(和最小值都行),关闭标识插入并做:

insert into t(<all columns including identity>) 
    select <all columns including identity>; 
+0

+1,我喜欢这个解决方案,因为它很干净,也是最好的实践。但我也会添加一条评论,在做这个过程来收集所有的信息/统计之前,可能是重复数量少,速度快/只是删除它们而不是插入数百万行和来回...... – MrSimpleMind

+0

@ MrSimpleMind。 。 。你是对的。如果只有少数几个重复项(比如说在成千上万行的表中有数千个),那么直接使用'delete'会更好。 –

+0

@戈登Linoof:谢谢你的回答。不幸的是,它显示我的Identify_INSERT未打开。运行代码的结果是一个空表。 – user2713440

6

如果您正在使用SQL Server,你可以使用从公共表表达式删除:

with cte as (
    select row_number() over(partition by SICComb, NameComb order by Col1) as row_num 
    from Table1 
) 
delete 
from cte 
where row_num > 1 

这里所有行都将被编号,你自己的序列每个单que组合SICComb + NameComb。您可以通过在over子句中选择order by来选择要删除的行。

+1

@ShahgholiArdalan不要碰我的代码。我相信在SQL中使用大写字母的传统应该消失,我总是将我的代码格式化为可读性,不要让我的答案更糟! –

+0

这似乎比从大量列和行中删除重复项以及包含唯一标识符的列的公认答案更好。 – Malcolm