挑战高手:SQL Server 2000, 一个表, 包含完全相同重复数据若干,怎么删除多余记录?

时间:2022-07-08 21:41:58
比如:
      字段名:  Col_A      Col_B     Col_C
       记录:    A            A        A
                 A            A    A
                 B            C        D
                 A            A        A
                 B            C        D  
                 B            D        D
                 A            A        A

 反正就是有完全相同记录!
 现在要留下完全相同记录中的一条,仅留一条,其余删除。
 结果是:    
      字段名:  Col_A      Col_B     Col_C
       记录:    A            A        A
                 B            C        D
                 B            D        D
 要求语句尽量简洁,一定要高效!
 尽管放马过来吧。

26 个解决方案

#1


这种表结构怎么高效的起来?
写存储过程:
原来的表名:table_a
先insert into table b select distinct * from table_a (会产生一个和table_a结构相同的表)
然后
delete from table_a;
最后
insert into table_a select * from table_b

#2


没有更快的办法?
这样还得建一个表,再删一个表,而且,把表中数据几乎都复制了一遍。
但是,我这个表中有50万条记录(不包括重复!),而且,有若干表都是这样。
你难道要我都copy一次?再删除一次?

#3


不是阿,insert into了以后建立的table_b是永久的了。下面这个proc一次就搞定了。
create procedure sp_cleardata
as
begin
  begin tran 
    insert into table b select distinct * from table_a 
  commit tran
  begin tran 
    delete from table_a
  commit tran

  begin tran 
    insert into table a select * from table_b 
  commit tran
end



#4


我说的是 insert 这个动作磁盘I/O操作太大。
虽然调用存储过程,就算你存储过程可以反复调用,还是要进行insert操作的。
能不能直接删除多余的?
能够直接delete就快多了。
你开始说出的这个办法我会,不过就是感觉慢。
求解决方案!

#5


关注。

#6


如果表结构跟你贴出来的结构完全一样,我想实现可能比较困难,但你的数据表中有一个iden或其它的主键字段话则有办法。

#7


没有ID,确实没有。
结构完全相同。
不是没事干为难大家。
确实不好搞定。
高人都来啊!

#8


select distinct * into table_b from table_a 
go
drop table table_a
go
sp_rename table_b,table_a
go
  

#9


看来还是要复制啊!
摩西,你的办法已经不错了!
不过还是不满足要求。

#10



csdn藏龙卧虎,我相信一定能够搞定这个问题的!
时间问题。

我等等等等等等等等等等等等等等等等等等等等等等等!

#11



lovesong() 的方法会慢吗?

你看一下到底是哪个环节慢?

改一点点

create procedure sp_cleardata
as
begin
  begin tran 
   insert into table #b select distinct * from table_a 

   delete from table_a
 
   insert into table_a select * from #b 
  commit tran
end

这种方法已经够快了!

直接删除,也要进行大量的比较

#12


to 太白
的确应该写在一个trans里面。
还有#b生成的是临时表吧?(重启会删掉)

#13


好,再等等。看还有哪个有更好的办法。
实在没有,只有这样了。分会给的。

#14


TO leeyoong(莫西):
 Drop table 是不能够恢复的。所以,大家研究一下,在事务处理中,这样用回不回出问题?比如不能回滚?

#15


to happyer(编程的兔子) :

"Drop table 是不能够恢复的" 这是什么意思!

我的方法为什么还不满足要求?能清楚地告诉我吗?

#16


你的方法“功能上”已经满足要求了!
完全满足!
不过,
在性能上,我原来一直认为写磁盘(读磁盘快)要慢很多,我假设有1000个表(夸张),而且,每个表都有几十万条记录,每个表都象我描述的那样,需要处理。
这样,光复制就需要很长时间啊。这个写磁盘的过程可是了不得!很恐怖的。
而且,系统又不能中断服务,还不能让数据库服务器忙于干这个,以至于别的操作无响应。
所以我说“不满足”是“从性能上”不满足。
那个“Drop table” 不像别的操作(比如delete table)可以用日志回滚。
drop是没有日志记录的!
这样,你又没有使用事务处理,所以很恐怖!
仅此而已。

大家继续!

#17


使用drop table的命令,仅针对一个独立的表,该表不可带外键连接和触发器等。

在这之前可以先提交数据写入新表的操作,成功建立新表后,那么再drop旧表,就没什么恐怖了!~

另外,对你的要求,我觉得还不如建立一系列的视图来得轻松,又无须大量的insert操作!提高效率又节省空间!不知意下如何?

#18


ORACLE中是非常容易解决的,用ROWID就行了。
delect from mytable x
where rowid <> (select max(rowid)
                  from mytable y
                 where y.field1 = x.field1
                   and y.field2 = x.field2
                   .....
                );

在SQL SERVER中有没有类似的方法?

#19


TO KingSunSha(弱水三千):
    我这个表没有ID,所以你那个max(rowid)不知道是否有用
    而且重复记录是“完全重复”,而且不知道重复次数。你看看本贴最前面例子。
    所以,好像不行啊。
TO leeyoong(莫西):
    不带外键好像不可能啊。
    我这里这么多表,肯定有一个表管理这些表的。(记录表名以及其功能,内容的分类……)
    现在已经不恐怖了。我是说  你原来没有提及事务处理。
   
    视图?你突然提到这件事,我牙齿还没刷呢!
    你是说用视图得到结果,而不需要实际处理重复值?
    那样以后冗余越来越多啊。
    可能理解偏差,望明告之。

#20


to :happyer(编程的兔子) 
RowID是Oracle的伪例,对于每一个表,系统自建的
对于Oracle,我认为KingSunSha的方法很不错

#21


原来如此。(错怪---我错了,我是妖怪)

#22


今天晚上人多。UP.

#23


to: KingSunSha(弱水三千) 

从几次您回答的问题来看,我发现您对ORACLE的ROWID AND ROWNUM 理解的特别的深,而且应用自如!我得向你学习一下!!!!

能不能给个QQ号??

#24


general2000(大小统吃):
我的QQ号:26357609(需要验证)

#25


不如在你生成这些行时就检查有无重复行,可以用触发器啊

#26


TO Billie_li:
        也有道理!
好,结束这个话题,给分喽!

#1


这种表结构怎么高效的起来?
写存储过程:
原来的表名:table_a
先insert into table b select distinct * from table_a (会产生一个和table_a结构相同的表)
然后
delete from table_a;
最后
insert into table_a select * from table_b

#2


没有更快的办法?
这样还得建一个表,再删一个表,而且,把表中数据几乎都复制了一遍。
但是,我这个表中有50万条记录(不包括重复!),而且,有若干表都是这样。
你难道要我都copy一次?再删除一次?

#3


不是阿,insert into了以后建立的table_b是永久的了。下面这个proc一次就搞定了。
create procedure sp_cleardata
as
begin
  begin tran 
    insert into table b select distinct * from table_a 
  commit tran
  begin tran 
    delete from table_a
  commit tran

  begin tran 
    insert into table a select * from table_b 
  commit tran
end



#4


我说的是 insert 这个动作磁盘I/O操作太大。
虽然调用存储过程,就算你存储过程可以反复调用,还是要进行insert操作的。
能不能直接删除多余的?
能够直接delete就快多了。
你开始说出的这个办法我会,不过就是感觉慢。
求解决方案!

#5


关注。

#6


如果表结构跟你贴出来的结构完全一样,我想实现可能比较困难,但你的数据表中有一个iden或其它的主键字段话则有办法。

#7


没有ID,确实没有。
结构完全相同。
不是没事干为难大家。
确实不好搞定。
高人都来啊!

#8


select distinct * into table_b from table_a 
go
drop table table_a
go
sp_rename table_b,table_a
go
  

#9


看来还是要复制啊!
摩西,你的办法已经不错了!
不过还是不满足要求。

#10



csdn藏龙卧虎,我相信一定能够搞定这个问题的!
时间问题。

我等等等等等等等等等等等等等等等等等等等等等等等!

#11



lovesong() 的方法会慢吗?

你看一下到底是哪个环节慢?

改一点点

create procedure sp_cleardata
as
begin
  begin tran 
   insert into table #b select distinct * from table_a 

   delete from table_a
 
   insert into table_a select * from #b 
  commit tran
end

这种方法已经够快了!

直接删除,也要进行大量的比较

#12


to 太白
的确应该写在一个trans里面。
还有#b生成的是临时表吧?(重启会删掉)

#13


好,再等等。看还有哪个有更好的办法。
实在没有,只有这样了。分会给的。

#14


TO leeyoong(莫西):
 Drop table 是不能够恢复的。所以,大家研究一下,在事务处理中,这样用回不回出问题?比如不能回滚?

#15


to happyer(编程的兔子) :

"Drop table 是不能够恢复的" 这是什么意思!

我的方法为什么还不满足要求?能清楚地告诉我吗?

#16


你的方法“功能上”已经满足要求了!
完全满足!
不过,
在性能上,我原来一直认为写磁盘(读磁盘快)要慢很多,我假设有1000个表(夸张),而且,每个表都有几十万条记录,每个表都象我描述的那样,需要处理。
这样,光复制就需要很长时间啊。这个写磁盘的过程可是了不得!很恐怖的。
而且,系统又不能中断服务,还不能让数据库服务器忙于干这个,以至于别的操作无响应。
所以我说“不满足”是“从性能上”不满足。
那个“Drop table” 不像别的操作(比如delete table)可以用日志回滚。
drop是没有日志记录的!
这样,你又没有使用事务处理,所以很恐怖!
仅此而已。

大家继续!

#17


使用drop table的命令,仅针对一个独立的表,该表不可带外键连接和触发器等。

在这之前可以先提交数据写入新表的操作,成功建立新表后,那么再drop旧表,就没什么恐怖了!~

另外,对你的要求,我觉得还不如建立一系列的视图来得轻松,又无须大量的insert操作!提高效率又节省空间!不知意下如何?

#18


ORACLE中是非常容易解决的,用ROWID就行了。
delect from mytable x
where rowid <> (select max(rowid)
                  from mytable y
                 where y.field1 = x.field1
                   and y.field2 = x.field2
                   .....
                );

在SQL SERVER中有没有类似的方法?

#19


TO KingSunSha(弱水三千):
    我这个表没有ID,所以你那个max(rowid)不知道是否有用
    而且重复记录是“完全重复”,而且不知道重复次数。你看看本贴最前面例子。
    所以,好像不行啊。
TO leeyoong(莫西):
    不带外键好像不可能啊。
    我这里这么多表,肯定有一个表管理这些表的。(记录表名以及其功能,内容的分类……)
    现在已经不恐怖了。我是说  你原来没有提及事务处理。
   
    视图?你突然提到这件事,我牙齿还没刷呢!
    你是说用视图得到结果,而不需要实际处理重复值?
    那样以后冗余越来越多啊。
    可能理解偏差,望明告之。

#20


to :happyer(编程的兔子) 
RowID是Oracle的伪例,对于每一个表,系统自建的
对于Oracle,我认为KingSunSha的方法很不错

#21


原来如此。(错怪---我错了,我是妖怪)

#22


今天晚上人多。UP.

#23


to: KingSunSha(弱水三千) 

从几次您回答的问题来看,我发现您对ORACLE的ROWID AND ROWNUM 理解的特别的深,而且应用自如!我得向你学习一下!!!!

能不能给个QQ号??

#24


general2000(大小统吃):
我的QQ号:26357609(需要验证)

#25


不如在你生成这些行时就检查有无重复行,可以用触发器啊

#26


TO Billie_li:
        也有道理!
好,结束这个话题,给分喽!