2010-08-07 70 views

回答

4
  1. 做一个查询,让你有资格作为复制
  2. 进行查询B中得到你想要保持
  3. 进行查询的行是删除有能力的所有行的行但不在B.

例子。

假设一个名为table的表,其中包含一个名为id的自动增量ID列和一个名为name的列,您要删除其中的双打。在每个名称中,您希望保留最早的记录(ID最低的那个)。

查询则看起来像:

SELECT * FROM table 
WHERE name IN (SELECT name FROM table GROUP BY name HAVING COUNT(*) > 1) 

查询B.将:

SELECT * FROM table 
WHERE id IN (SELECT min(id) FROM table GROUP BY name) 

现在将这些形成删除查询:

DELETE FROM table 
WHERE name IN (SELECT name FROM table GROUP BY name HAVING COUNT(*) > 1) 
AND NOT id IN (SELECT min(id) FROM table GROUP BY name) 

在这个例子中,在你可以忽略第一个查询,但是当事情变得更复杂时,这是一个很好的额外保障措施。

1

你不行。 完全重复记录(每个字段相同的记录)不能一个删除,因为在删除查询中,您不能在Where子句中区分它们。
唯一的办法是做一个select distinct查询来选择没有重复的所有行,然后将它们插入一个空的表中。

如果您没有完全重复的记录,那么问题的解释不正确,并且您不希望删除重复记录,因为没有任何记录。具有不完整的相同字段的行不重复。在这种情况下,您希望删除具有相同字段的行,在这种情况下,如果某个字段或字段集不相同,则必须指定要离开的行。

+0

我不认为这是真的。假设你从一个表中选择了全部,再加上一个ROW_NUMBER()列。这些行将以聚簇索引顺序返回,并且您将为每个行获取不同的行号值。然后您可以使用它来区分WHERE子句中的重复项。 – Yellowfog 2010-08-07 19:07:30

+0

row_number是一个与order by语句一起使用的函数,只能在select查询中使用。这只是row_number不能直接参与delete语句的原因之一。我在互联网上找到的解决方案之一是创建一个单独的表,将row_number作为新字段引入,然后执行删除语句。这不是作者想要的。 – AlexanderMP 2010-08-07 22:03:48

0

通过使用公用表表达式(CTE),您可以毫无问题地完成此任务,而无需使用任何临时表。如果删除是针对高流量表,请注意。删除大量的数据可能会导致锁定和阻塞,同时会传输转录。

注意:此代码没有进行任何测试,但应该可以工作(SQL 2005及更高版本)。

/* Create test data with duplicates */ 
declare @TestTable Table (Col1 int) 

insert into @TestTable 

select 1 union all 
select 1 union all 
select 2 union all 
select 3 union all 
select 3 union all 
select 4 
; 
/* Create CTE to number all duplicates (gives a running number to all identical values in Col1) */ 
with FindDupes as 
(
Select Col1,ROW_NUMBER() over (partition by Col1 order by Col1) RN 

from @TestTable 
) 
/* Delete the duplicates (anything that has a higher rownumber than one) */ 
Delete from FindDupes where RN>1 
; 

/* Select the remaining data from the table */ 
Select * from @TestTable 
-1

我觉得这个查询将正常工作:

delete from table where id in (select count(*)c from table group by id having c > 1)