access 删除重复数据 ,并保留一条,数据量大,如何提高速度的问题。

时间:2020-12-17 23:21:11
access中有这样一个表crjsj(78万条数据) ,其中有部分数据为:
kh  id          time8          date8    mjjbh mjkzqbh syqk crjqk
9393443 14227993 18:00:00 2009-04-20 1 10979 1 0
9393443 14227996 18:00:00 2009-04-20 1 10979 1 0
9393443 13798958 18:00:00 2009-04-03 1 10979 1 0
9393443 13798988 18:00:00 2009-04-03 1 10979 1 0
9393443 13799004 18:00:00 2009-04-03 1 10979 1 0
9393443 13799176 18:00:00 2009-04-03 1 10979 1 0
9393443 13799204 18:00:00 2009-04-03 1 10979 1 0
9393443 13799218 18:00:00 2009-04-03 1 10979 1 0
9393443 13799233 18:00:00 2009-04-03 1 10979 1 0
9393443 13799251 18:00:00 2009-04-03 1 10979 1 0
9393473 14008199 18:00:00 2009-04-15 1 26312 1 0
9393473 14008210 18:00:00 2009-04-15 1 26312 1 0
9393473 14008227 18:00:00 2009-04-15 1 26312 1 0
9393473 14008234 18:00:00 2009-04-15 1 26312 1 0
9393473 14008235 18:00:00 2009-04-15 1 26312 1 0
(kh字段也有重复的和不重复的)。
有很多重复数据,现在需要删掉重复数据,只保存重复数据中的一条
曾经使用过语句为:delete from crjsj where id not in (select max(id) from crjsj group by kh,time8 ,date8 )
但是效率非常差,删除了1个小时连一半都没删完,希望朋友们能提供一个更高效率的方法,并给出例子,谢谢。

17 个解决方案

#1


数据显示有点乱,改一下
kh          id       time8         date8    mjjbh  mjkzqbh   syqk  crjqk 
9393443   14227993   18:00:00   2009-04-20   1     10979      1     0 
9393443   14227996   18:00:00   2009-04-20   1     10979      1     0 
9393443   13798958   18:00:00   2009-04-03   1     10979      1     0 
9393443   13798988   18:00:00   2009-04-03   1     10979      1     0 
9393443   13799004   18:00:00   2009-04-03   1     10979      1     0 
9393443   13799176   18:00:00   2009-04-03   1     10979      1     0 
9393443   13799204   18:00:00   2009-04-03   1     10979      1     0 
9393443   13799218   18:00:00   2009-04-03   1     10979      1     0 
9393443   13799233   18:00:00   2009-04-03   1     10979      1     0 
9393443   13799251   18:00:00   2009-04-03   1     10979      1     0 
9393473   14008199   18:00:00   2009-04-15   1     26312      1     0 
9393473   14008210   18:00:00   2009-04-15   1     26312      1     0 
9393473   14008227   18:00:00   2009-04-15   1     26312      1     0 
9393473   14008234   18:00:00   2009-04-15   1     26312      1     0 
9393473   14008235   18:00:00   2009-04-15   1     26312      1     0 

#2


delete from crjsj t where exists (select 1 from crjsj where kh=t.kh and time8=t.time8 and date8=t.date8 and id>t.id)

#3


引用 2 楼 wufeng4552 的回复:
SQL codedelete from crjsj t where exists (select 1 from crjsj where kh=t.kh and time8=t.time8 and date8=t.date8 and id>t.id)

UP

#4


好像不行,运行后,效率还是不高,和in比几乎没有提高

#5


引用 4 楼 spewen 的回复:
好像不行,运行后,效率还是不高,和in比几乎没有提高

要不就通过临时表,
先筛选出记录放在临时表,删除原表内容,再插入原表,删除临时表.

#6


引用 5 楼 htl258 的回复:
引用 4 楼 spewen 的回复:
好像不行,运行后,效率还是不高,和in比几乎没有提高 
 
要不就通过临时表, 
先筛选出记录放在临时表,删除原表内容,再插入原表,删除临时表. 


我也想到这个办法了,不过就是不知道怎么检索出来后放入临时表,麻烦能给我写个例子吗?谢谢!

#7


引用 6 楼 spewen 的回复:
引用 5 楼 htl258 的回复:
引用 4 楼 spewen 的回复: 
好像不行,运行后,效率还是不高,和in比几乎没有提高 

要不就通过临时表, 
先筛选出记录放在临时表,删除原表内容,再插入原表,删除临时表. 
 

我也想到这个办法了,不过就是不知道怎么检索出来后放入临时表,麻烦能给我写个例子吗?谢谢!


select * into tmptb from crjsj where id not in (select max(id) from crjsj group by kh,time8 ,date8)


就像这样.

#8


插入的时候还是使用到了in 效率不高啊,不知道还有什么好的方法

#9


引用 8 楼 spewen 的回复:
插入的时候还是使用到了in 效率不高啊,不知道还有什么好的方法

/*

select * from tb t where not exists(select 1 from tb where kh=t.kh and time8=t.time8 and date8=t.date8 and mjkzqbh=t.mjkzqbh and id<t.id)

#10


数据多,,删除,插入临时表,,,比前面的几种方法都更慢...

#11


看来还是没人解决

#12


从表中删除重复记录需要两个步骤。第一步,复制包含重复记录的表的结构,生成包含重复记录的所有字段的主键。第二步,创建并运行从原始表到新表的追加查询。由于主键字段不能包含重复记录,因此这一过程将生成不含重复记录的表。

复制该表并使包含重复项的字段成为主键
在“数据库”窗口中选择该表。 
单击工具栏上的“复制”。 
然后单击工具栏上的“粘贴”。 
在“粘贴表方式”对话框中,键入已复制的表的名称,单击“只粘贴结构”,然后单击“确定”。 
在“设计”视图中打开新表,选择复制表中包含重复记录的字段。 
单击工具栏上的“主键”以基于选定字段创建主键。 
保存并关闭该表。 
仅将唯一的记录追加到新表
基于包含重复记录的原始表创建一个新查询。 
在“查询设计”视图中,单击工具栏上的“查询类型”,然后单击“追加查询”。 
在“追加”对话框中,在“表名称”列表中单击新表的名称,然后单击“确定”。 
添加来自原始表的所有字段,方法是将星号 (*) 拖动到查询设计网格中。 
单击工具栏上的“运行”。 
当您收到将要追加行的消息时,请单击“是”。 
当您收到 Microsoft Access 无法在追加查询中追加所有记录时,请单击“是”。这样,只会将不重复的记录传输到新表中,放弃重复记录。 
打开该表查看结果。如果您确定新表的不重复记录是正确的,则可以删除原始表,然后使用原始表的名称重命名新表。

#13


引用楼主 spewen 的回复:
access中有这样一个表crjsj(78万条数据)...........


-.-
你想过这样一个数量级的记录集 运算的用时了么?

计算机是一个快的运算工具,但它也不是万能的...
实际上任何一条SQL 语句的都要完成从第一条记录到最后一条记录的判断和运算...
当成为数据巨集时尽量避免大规模的更新与删除操作...

你现在明显就是给自己制造麻烦,这时你应该只使用查询查看不重复的记录,而不是将不重复的记录生成一个新的表或删除那些重复的记录...
实际上就是你只使用查询查看不重复的记录,也同样需要很长的时间...在数据库选项设置中一般只显示前1000条记录...如果将 78 万条记录全部显示出来,那么你一定有事儿干了...

劝你想想别的解决思路,也许会柳暗花明又一村...

#14


同问哦~~!

#15


这个问题怎么还没有人想出什么先进的方法啊?我现在只能通过vb来写个小程序检查了!删除了!但是好像还是有很多缺陷的!

#16


没想到数据量,比我的还多的!我以为我十来万就不少的了,现在看到更多的了!

#17


DELETE a 
-- SELECT * 
FROM dm_s_pt a
INNER JOIN
(
SELECT * FROM (
SELECT a.*,
ROW_NUMBER() OVER (PARTITION BY a.Batch,a.Index_code,a.Period,a.Region_code,
a.Operator_code,a.Business,a.Technology,a.Customer_type
order by b.Dp_id ASC) AS Row_Num 
FROM dm_s_pt a INNER JOIN dm_s_pt b
ON a.Batch = b.Batch
AND a.Index_code = b.Index_code
AND a.Period=b.Period
AND a.Region_code = b.Region_code
AND ISNULL(a.Operator_code,'') = ISNULL(b.Operator_code,'')
AND ISNULL(a.Business,'') = ISNULL(b.Business,'')
AND ISNULL(a.Technology,'') = ISNULL(b.Technology,'')
AND ISNULL(a.Customer_type,'') = ISNULL(b.Customer_type,'')
AND ISNULL(a.Data_flag,'-1') = ISNULL(b.Data_flag,'-1')
AND a.Dp_id<>b.Dp_id
AND a.Data_flag='SOURCE'
) t WHERE Row_Num>1 --挑出重复行并编号,删除编号>1的行
) b
ON a.Batch = b.Batch
AND a.Index_code = b.Index_code
AND a.Period=b.Period
AND a.Region_code = b.Region_code
AND ISNULL(a.Operator_code,'') = ISNULL(b.Operator_code,'')
AND ISNULL(a.Business,'') = ISNULL(b.Business,'')
AND ISNULL(a.Technology,'') = ISNULL(b.Technology,'')
AND ISNULL(a.Customer_type,'') = ISNULL(b.Customer_type,'')
AND ISNULL(a.Data_flag,'-1') = ISNULL(b.Data_flag,'-1')
AND ISNULL(a.Dp_id,'-1') = ISNULL(b.Dp_id,'-1')
AND ISNULL(a.Value,'-999') = ISNULL(b.Value,'-999')

#1


数据显示有点乱,改一下
kh          id       time8         date8    mjjbh  mjkzqbh   syqk  crjqk 
9393443   14227993   18:00:00   2009-04-20   1     10979      1     0 
9393443   14227996   18:00:00   2009-04-20   1     10979      1     0 
9393443   13798958   18:00:00   2009-04-03   1     10979      1     0 
9393443   13798988   18:00:00   2009-04-03   1     10979      1     0 
9393443   13799004   18:00:00   2009-04-03   1     10979      1     0 
9393443   13799176   18:00:00   2009-04-03   1     10979      1     0 
9393443   13799204   18:00:00   2009-04-03   1     10979      1     0 
9393443   13799218   18:00:00   2009-04-03   1     10979      1     0 
9393443   13799233   18:00:00   2009-04-03   1     10979      1     0 
9393443   13799251   18:00:00   2009-04-03   1     10979      1     0 
9393473   14008199   18:00:00   2009-04-15   1     26312      1     0 
9393473   14008210   18:00:00   2009-04-15   1     26312      1     0 
9393473   14008227   18:00:00   2009-04-15   1     26312      1     0 
9393473   14008234   18:00:00   2009-04-15   1     26312      1     0 
9393473   14008235   18:00:00   2009-04-15   1     26312      1     0 

#2


delete from crjsj t where exists (select 1 from crjsj where kh=t.kh and time8=t.time8 and date8=t.date8 and id>t.id)

#3


引用 2 楼 wufeng4552 的回复:
SQL codedelete from crjsj t where exists (select 1 from crjsj where kh=t.kh and time8=t.time8 and date8=t.date8 and id>t.id)

UP

#4


好像不行,运行后,效率还是不高,和in比几乎没有提高

#5


引用 4 楼 spewen 的回复:
好像不行,运行后,效率还是不高,和in比几乎没有提高

要不就通过临时表,
先筛选出记录放在临时表,删除原表内容,再插入原表,删除临时表.

#6


引用 5 楼 htl258 的回复:
引用 4 楼 spewen 的回复:
好像不行,运行后,效率还是不高,和in比几乎没有提高 
 
要不就通过临时表, 
先筛选出记录放在临时表,删除原表内容,再插入原表,删除临时表. 


我也想到这个办法了,不过就是不知道怎么检索出来后放入临时表,麻烦能给我写个例子吗?谢谢!

#7


引用 6 楼 spewen 的回复:
引用 5 楼 htl258 的回复:
引用 4 楼 spewen 的回复: 
好像不行,运行后,效率还是不高,和in比几乎没有提高 

要不就通过临时表, 
先筛选出记录放在临时表,删除原表内容,再插入原表,删除临时表. 
 

我也想到这个办法了,不过就是不知道怎么检索出来后放入临时表,麻烦能给我写个例子吗?谢谢!


select * into tmptb from crjsj where id not in (select max(id) from crjsj group by kh,time8 ,date8)


就像这样.

#8


插入的时候还是使用到了in 效率不高啊,不知道还有什么好的方法

#9


引用 8 楼 spewen 的回复:
插入的时候还是使用到了in 效率不高啊,不知道还有什么好的方法

/*

select * from tb t where not exists(select 1 from tb where kh=t.kh and time8=t.time8 and date8=t.date8 and mjkzqbh=t.mjkzqbh and id<t.id)

#10


数据多,,删除,插入临时表,,,比前面的几种方法都更慢...

#11


看来还是没人解决

#12


从表中删除重复记录需要两个步骤。第一步,复制包含重复记录的表的结构,生成包含重复记录的所有字段的主键。第二步,创建并运行从原始表到新表的追加查询。由于主键字段不能包含重复记录,因此这一过程将生成不含重复记录的表。

复制该表并使包含重复项的字段成为主键
在“数据库”窗口中选择该表。 
单击工具栏上的“复制”。 
然后单击工具栏上的“粘贴”。 
在“粘贴表方式”对话框中,键入已复制的表的名称,单击“只粘贴结构”,然后单击“确定”。 
在“设计”视图中打开新表,选择复制表中包含重复记录的字段。 
单击工具栏上的“主键”以基于选定字段创建主键。 
保存并关闭该表。 
仅将唯一的记录追加到新表
基于包含重复记录的原始表创建一个新查询。 
在“查询设计”视图中,单击工具栏上的“查询类型”,然后单击“追加查询”。 
在“追加”对话框中,在“表名称”列表中单击新表的名称,然后单击“确定”。 
添加来自原始表的所有字段,方法是将星号 (*) 拖动到查询设计网格中。 
单击工具栏上的“运行”。 
当您收到将要追加行的消息时,请单击“是”。 
当您收到 Microsoft Access 无法在追加查询中追加所有记录时,请单击“是”。这样,只会将不重复的记录传输到新表中,放弃重复记录。 
打开该表查看结果。如果您确定新表的不重复记录是正确的,则可以删除原始表,然后使用原始表的名称重命名新表。

#13


引用楼主 spewen 的回复:
access中有这样一个表crjsj(78万条数据)...........


-.-
你想过这样一个数量级的记录集 运算的用时了么?

计算机是一个快的运算工具,但它也不是万能的...
实际上任何一条SQL 语句的都要完成从第一条记录到最后一条记录的判断和运算...
当成为数据巨集时尽量避免大规模的更新与删除操作...

你现在明显就是给自己制造麻烦,这时你应该只使用查询查看不重复的记录,而不是将不重复的记录生成一个新的表或删除那些重复的记录...
实际上就是你只使用查询查看不重复的记录,也同样需要很长的时间...在数据库选项设置中一般只显示前1000条记录...如果将 78 万条记录全部显示出来,那么你一定有事儿干了...

劝你想想别的解决思路,也许会柳暗花明又一村...

#14


同问哦~~!

#15


这个问题怎么还没有人想出什么先进的方法啊?我现在只能通过vb来写个小程序检查了!删除了!但是好像还是有很多缺陷的!

#16


没想到数据量,比我的还多的!我以为我十来万就不少的了,现在看到更多的了!

#17


DELETE a 
-- SELECT * 
FROM dm_s_pt a
INNER JOIN
(
SELECT * FROM (
SELECT a.*,
ROW_NUMBER() OVER (PARTITION BY a.Batch,a.Index_code,a.Period,a.Region_code,
a.Operator_code,a.Business,a.Technology,a.Customer_type
order by b.Dp_id ASC) AS Row_Num 
FROM dm_s_pt a INNER JOIN dm_s_pt b
ON a.Batch = b.Batch
AND a.Index_code = b.Index_code
AND a.Period=b.Period
AND a.Region_code = b.Region_code
AND ISNULL(a.Operator_code,'') = ISNULL(b.Operator_code,'')
AND ISNULL(a.Business,'') = ISNULL(b.Business,'')
AND ISNULL(a.Technology,'') = ISNULL(b.Technology,'')
AND ISNULL(a.Customer_type,'') = ISNULL(b.Customer_type,'')
AND ISNULL(a.Data_flag,'-1') = ISNULL(b.Data_flag,'-1')
AND a.Dp_id<>b.Dp_id
AND a.Data_flag='SOURCE'
) t WHERE Row_Num>1 --挑出重复行并编号,删除编号>1的行
) b
ON a.Batch = b.Batch
AND a.Index_code = b.Index_code
AND a.Period=b.Period
AND a.Region_code = b.Region_code
AND ISNULL(a.Operator_code,'') = ISNULL(b.Operator_code,'')
AND ISNULL(a.Business,'') = ISNULL(b.Business,'')
AND ISNULL(a.Technology,'') = ISNULL(b.Technology,'')
AND ISNULL(a.Customer_type,'') = ISNULL(b.Customer_type,'')
AND ISNULL(a.Data_flag,'-1') = ISNULL(b.Data_flag,'-1')
AND ISNULL(a.Dp_id,'-1') = ISNULL(b.Dp_id,'-1')
AND ISNULL(a.Value,'-999') = ISNULL(b.Value,'-999')