删除表中的重复项

删除表中的重复项

问题描述:

数据库类型为PostGres 8.3。删除表中的重复项

如果我写道:

SELECT field1, field2, field3, count(*) 
FROM table1 
GROUP BY field1, field2, field3 having count(*) > 1; 

我有一些行有超过1.如何取出重复计数(我还是想1排为他们每个人的,而不是排+1。 ..我不想将它们全部删除)

例:

1-2-3 
1-2-3 
1-2-3 
2-3-4 
4-5-6 

应该改为:

1-2-3 
2-3-4 
4-5-6 

我发现的唯一答案是there,但我想知道如果我能做到这一点没有哈希列。

警告 我没有用一个唯一的编号PK了,所以我不能使用分钟(...)的技术。 PK是3个领域。

+0

我不确定我是否理解正确。你说“PK是3场” - 那么你怎么像表1-2-3中的重复记录一样。纠正我,如果我错了。 – 2008-10-28 15:02:00

+0

PK是在3个领域,我们必须删除他们的合并(长篇故事),现在我们需要把它放回去。我们有一些我们想要起飞的重复。 – 2008-10-28 15:10:31

这是所有表应具有主键的许多原因之一(不一定是ID号或IDENTITY,而是一个或多个列的唯一标识行和在数据库中实施其唯一性的组合) 。

最好的办法是这样的:

SELECT field1, field2, field3, count(*) 
INTO temp_table1 
FROM table1 
GROUP BY field1, field2, field3 having count(*) > 1 

DELETE T1 
FROM table1 T1 
INNER JOIN (SELECT field1, field2, field3 
     FROM table1 
     GROUP BY field1, field2, field3 having count(*) > 1) SQ ON 
      SQ.field1 = T1.field1 AND 
      SQ.field2 = T1.field2 AND 
      SQ.field3 = T1.field3 

INSERT INTO table1 (field1, field2, field3) 
SELECT field1, field2, field3 
FROM temp_table1 

DROP TABLE temp_table1 
+0

我目前正在尝试你的建议。 +1 – 2008-10-28 15:25:09

+0

它工作thx,我已经修改DELETE T1的一些东西不起作用,我不得不把T1之后的T1作为T1。很少有这样的事情。但这个解决方案在这里很快并且很成功。 – 2008-10-28 16:33:14

一个可能的答案是:

CREATE <temporary table> (<correct structure for table being cleaned>); 
BEGIN WORK; -- if needed 
INSERT INTO <temporary table> SELECT DISTINCT * FROM <source table>; 
DELETE FROM <source table> 
INSERT INTO <source table> SELECT * FROM <temporary table>; 
COMMIT WORK; -- needed 
DROP <temporary table>; 

我不知道的“工作”是否需要在交易声明,亦无论是明确的开始,有必要在PostgreSQL的。但是这个概念适用于任何DBMS。

唯一要注意的是参照约束,特别是触发删除操作。如果存在的话,这可能不太令人满意。

这将使用OID对象ID(如果该表是用它创建):

DELETE FROM table1 
WHERE OID NOT IN (SELECT MIN (OID) 
           FROM table1 
          GROUP BY field1, field2, field3) 

嗯,我会误解的东西,但我我会说:

SELECT DISTINCT field1,field2,field3 FROM table1

太容易变好了? ^^

使用TSQL,不知道如果Postgres支持用临时表,但你可以选择到一个临时表,然后通过循环和删除和插入您的结果放回原

-- **Disclaimer** using TSQL 
-- You could select your records into a temp table with a pk 
Create Table #dupes 
([id] int not null identity(1,1), f1 int, f2 int, f3 int) 

Insert Into #dupes (f1,f2,f3) values (1,2,3) 
Insert Into #dupes (f1,f2,f3) values (1,2,3) 
Insert Into #dupes (f1,f2,f3) values (1,2,3) 
Insert Into #dupes (f1,f2,f3) values (2,3,4) 
Insert Into #dupes (f1,f2,f3) values (4,5,6) 
Insert Into #dupes (f1,f2,f3) values (4,5,6) 
Insert Into #dupes (f1,f2,f3) values (4,5,6) 
Insert Into #dupes (f1,f2,f3) values (7,8,9) 

Select f1,f2,f3 From #dupes 

Declare @rowCount int 
Declare @counter int 
Set @counter = 1 
Set @rowCount = (Select Count([id]) from #dupes) 

while (@counter < @rowCount + 1) 
    Begin 
     Delete From #dupes 
     Where [Id] <> 
      (Select [id] From #dupes where [id][email protected]) 
       and 
      (
       [f1] = (Select [f1] from #dupes where [id][email protected]) 
       and 
       [f2] = (Select [f2] from #dupes where [id][email protected]) 
       and 
       [f3] = (Select [f3] from #dupes where [id][email protected]) 
      ) 
     Set @counter = @counter + 1 
    End 

Select f1,f2,f3 From #dupes -- You could take these results and pump them back into --your original table 

Drop Table #dupes 

测试这对MS SQL Server 2000.不熟悉Postgres的选项,但也许这会导致你在一个正确的方向。

这是我发现的最简单的方法:

Postgre SQL语法:

CREATE TABLE tmp AS SELECT distinct * FROM table1 
truncate table table1 
insert into table1 select * from tmp 
drop table tmp 

T-SQL语法:

select distinct * into #tmp from table1 
truncate table table1 
insert into table1 select * from #tmp 
drop table #tmp 

一个好的Answer对于这个问题,但对于SQL Server。它使用SQL Server提供的ROWCOUNT,以达到良好的效果。我从来没有使用PostgreSQL,因此不知道PostgreSQL中ROWCOUNT的等价物。