Suchen Sie mit PostgreSQL nach doppelten Zeilen

72

Wir haben eine Tabelle mit Fotos mit den folgenden Spalten:

id, merchant_id, url 

Diese Tabelle enthält doppelte Werte für die Kombination merchant_id, url. Es ist also möglich, dass eine Zeile mehrmals angezeigt wird.

234 some_merchant  http://www.some-image-url.com/abscde1213
235 some_merchant  http://www.some-image-url.com/abscde1213
236 some_merchant  http://www.some-image-url.com/abscde1213

Was ist der beste Weg, um diese Duplikate zu löschen? (Ich benutze PostgreSQL 9.2 und Rails 3.)

schlubbi
quelle
1
Ist Ihre ID-Spalte eindeutig? Ich sehe 234 3 Mal, aber Sie sagen, Ihre Merchant_ID und URL sind die doppelten Werte.
sgeddes
Mögliches Duplikat von stackoverflow.com/questions/1746213/…
Entschuldigung für die Verwirrung. Die ID im obigen Beispiel sollte eindeutig sein. danke für die korrekte bearbeitung. Die Lösung hier stackackflow.com/questions/1746213/… funktioniert in meinem Fall nicht.
Schlubbi

Antworten:

125

Hier ist meine Meinung dazu.

select * from (
  SELECT id,
  ROW_NUMBER() OVER(PARTITION BY merchant_Id, url ORDER BY id asc) AS Row
  FROM Photos
) dups
where 
dups.Row > 1

Spielen Sie mit der Bestellung, indem Sie die zu löschenden Datensätze an Ihre Spezifikation anpassen.

SQL Fiddle => http://sqlfiddle.com/#!15/d6941/1/0


SQL Fiddle für Postgres 9.2 wird nicht mehr unterstützt. Aktualisieren von SQL Fiddle auf postgres 9.3

MatthewJ
quelle
3
Das funktioniert wie ein Zauber, aber wie löscht man die mit dieser Abfrage gefundenen Duplikate?
Trasplazio Garzuglio
Wenn wir dasselbe dreimal wiederholen, werden Take 2 und Take 3 als Ergebnis genommen. Wie kann ich das beheben?
Fausto Carvalho Marques Silva
Es ist ein bisschen unklar, was Sie versuchen zu tun; Die Antwort zeigt unter Verwendung des SQL-Geigen-Links, wie Zeilen basierend auf definierten Spalten gelöscht werden. Sie sollten wahrscheinlich eine neue Frage mit bestimmten Schritten zur Reproduktion öffnen.
MatthewJ
Könnten Sie erklären, was es tatsächlich tut von ROW_NUMBER() OVER(PARTITION BY merchant_Id, url ORDER BY id asc)
Nomadme
1
Nein, wird es nicht, genau deshalb überprüfen Sie Zeilen> 1. Siehe die SQL-Geige.
MatthewJ
10

Der zweite Teil der Antwort von sgeddes funktioniert nicht mit Postgres (die Geige verwendet MySQL). Hier ist eine aktualisierte Version seiner Antwort mit Postgres: http://sqlfiddle.com/#!12/6b1a7/1

DELETE FROM Photos AS P1  
USING Photos AS P2
WHERE P1.id > P2.id
   AND P1.merchant_id = P2.merchant_id  
   AND P1.url = P2.url;  
11101101b
quelle
6

Ich sehe ein paar Optionen für Sie.

Verwenden Sie für eine schnelle Vorgehensweise Folgendes: Es wird davon ausgegangen, dass Ihre ID-Spalte nicht eindeutig ist, wie Sie oben mehrfach erwähnt haben 234:

CREATE TABLE tmpPhotos AS SELECT DISTINCT * FROM Photos;
DROP TABLE Photos;
ALTER TABLE tmpPhotos RENAME TO Photos;

Hier ist die SQL-Geige .

Sie müssen Ihre Einschränkungen wieder zur Tabelle hinzufügen, falls vorhanden.

Wenn Ihre ID-Spalte eindeutig ist, können Sie Ihre niedrigste ID beibehalten:

DELETE FROM P1  
USING Photos P1, Photos P2
WHERE P1.id > P2.id
   AND P1.merchant_id = P2.merchant_id  
   AND P1.url = P2.url;  

Und die Geige .

sgeddes
quelle
2
Die ID ist in meinem Fall eindeutig. Ich habe es in meinem Beispielcode einfach falsch gemacht. Ich erhalte jedoch eine Fehlermeldung, wenn ich versuche, Ihre zweite Lösung zu verwenden. ERROR: relation "p1" does not exist
Schlubbi
@StefanSchmidt Ich habe behoben, dass es auf Postgres anstelle von MySQL ausgeführt wird: sqlfiddle.com/#!12/6b1a7/1
11101101b