2008-10-28 17 views
5

Typ bazy danych to PostGres 8.3.Usuń duplikat z tabeli

Gdybym napisał:

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

mam kilka wierszy, które mają grubość ponad 1. Jak mogę wykupić duplikat (ja nadal chcę 1 wiersz dla każdego z nich, zamiast +1 wiersz. .. nie chcę je wszystkie usunąć)

. Przykład:

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

powinien stać:

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

Jedyna odpowiedź, którą znalazłem to there, ale zastanawiam się, czy mógłbym to zrobić bez kolumny hash.

Warning nie mam PK z unikalnym numerem, więc nie mogę używać techniki min (...). PK to 3 pola.

+0

Nie jestem pewien, czy rozumiem to dobrze. Mówisz "PK to 3 pola" - to dlaczego masz duplikaty w tabeli jak wiele rekordów 1-2-3. Popraw mnie, jeśli się mylę. –

+0

PK znajdowało się na 3 polach, musieliśmy je usunąć w celu scalenia (długa historia), teraz musimy je odłożyć. Mamy trochę duplikatu, który chcielibyśmy wystartować. –

Odpowiedz

6

Jest to jeden z wielu powodów, dla których wszystkie tabele powinny mieć klucz podstawowy (niekoniecznie numer identyfikacyjny lub TOŻSAMOŚĆ, ale kombinacja co najmniej jednej kolumny, która jednoznacznie identyfikuje wiersz i która ma wymuszoną unikalność w bazie danych) .

Najprościej jest coś takiego:

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

Obecnie próbuję twojej sugestii. +1 –

+0

Działa thx, mam zmodyfikowane kilka rzeczy jak DELETE T1 nie działa, musiałem umieścić T1 po FROM table1 jako T1. Niewiele takich rzeczy. Ale rozwiązanie było szybkie i skuteczne. –

+0

Cieszę się, że to zadziałało. Dzięki za wskazanie mojego widoku na alias T1. Poprawiłem to w skrypcie. –

0

Jedną z możliwych odpowiedzi brzmi:

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>; 

Nie jestem pewien, czy „praca” jest potrzebne na wyciągach transakcji, ani czy jest konieczne wyraźne BEGIN w PostgreSQL. Ale koncepcja dotyczy dowolnego DBMS.

Jedyną rzeczą, na którą należy zwrócić uwagę, są ograniczenia referencyjne, w szczególności uruchamiane operacje usuwania. Jeśli takie istnieją, może okazać się mniej satysfakcjonujące.

0

ten użyje identyfikatora OID Object (jeśli tabela została stworzona z nim):

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

Cóż mam rozumieją coś, ale ja odpowie:

SELECT DISTINCT pole1, pole2, pole3 Z tabeli1

Zbyt łatwo być dobrym? ^^

+0

Myślę, że Daok chce usunąć wszystkie oprócz jednego z duplikatów. –

0

Korzystanie TSQL, nie wiem, czy PostgreSQL obsługuje tabele tymczasowe, ale można wybrać do tabeli temp, a następnie pętli i usunąć i wstawić swoje wyniki z powrotem do oryginalnego

-- **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 

przetestowane na SM SQL Server 2000. Nie zna opcji PostgreSta, ale może to doprowadzi cię we właściwym kierunku.

0

Jest to najprostsza metoda znalazłem:

Postgre SQL Składnia:

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

T-SQL Składnia:

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

Funkcja przycinania nie działa, jeśli istnieją ograniczenia klucza obcego – kd7

+0

prawo, upuść i ponownie dodaj wiązania po obcięciu –

0

Dobrym Answer tego problemu, ale dla SQL Server. Używa ROWCOUNT, że SQL Server oferuje, na dobry efekt. Nigdy nie używałem PostgreSQL i dlatego nie znam odpowiednika ROWCOUNT w PostgreSQL.

Powiązane problemy