2008-10-28 137 views
5

數據庫類型爲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

回答

6

這是所有表應具有主鍵的許多原因之一(不一定是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

0

一個可能的答案是:

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。

唯一要注意的是參照約束,特別是觸發刪除操作。如果存在的話,這可能不太令人滿意。

0

這將使用OID對象ID(如果該表是用它創建):

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

嗯,我會誤解的東西,但我我會說:

SELECT DISTINCT field1,field2,field3 FROM table1

太容易變好了? ^^

0

使用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的選項,但也許這會導致你在一個正確的方向。

0

這是我發現的最簡單的方法:

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 
0

一個好的Answer對於這個問題,但對於SQL Server。它使用SQL Server提供的ROWCOUNT,以達到良好的效果。我從來沒有使用PostgreSQL,因此不知道PostgreSQL中ROWCOUNT的等價物。