doppelte Sätze löschen

anthu

Benutzer
Beiträge
5
Hallo,

ein uraltes Thema: wie lösche ich doppelte Datensätze in einer Tabelle?

Ich habe hier eine Tabelle mit vielen, vielen Feldern. Eines dieser Felder beinhaltet einen Termin, der mehrfach vorkommen kann, und ich möchte in der Tabelle alle Sätze so löschen, daß jeder Termin nur noch 1x übrig bleibt. Welchen Inhalt die anderen Felder haben und welcher Satz davon übrig bleibt interessiert nicht mehr.

Prinzipiell liefert diese Abfrage alle eindeutigen Terminsätze:
select distinct row_number() over(order by termin), termin from tmpLLast group by termin

Also dachte ich das:
delete from tmpLLast where ROW_NUMBER() not in (select distinct row_number() over(order by termin) from tmpLLast group by termin)

zum Erfolg führt. Statt ein n Sätze gelöscht gibt´s als Ergebnis nur ein Incorrect syntax near 'ROW_NUMBER', expected 'OVER'. Er stört sich an "delete from tmpLLast where ROW_NUMBER()", denn die Anweisung delete from tmpLLast where ROW_NUMBER() = 1 funktioniert auch nicht.

Hat noch jemand eine Idee wie ich die Sätze löschen kann?

Danke und Gruß
Andreas
 
Werbung:
ROW_NUMBER() wird zur Laufzeit berechnet, das kannst du nicht als Kriterium im WHERE-Teil verwenden. Wenn es keinen eindeutigen PK gibt der die Sätze doch irgendwie unterscheidet ist das nicht so banal. Das leichteste wird es sein die selbe Tabelle nochmal als Temp-Tabelle anzulegen, mit INSERT INTO temp SELECT DISTINCT * FROM tabelle alles da rein zu schieben, die Daten in der Haupttabelle zu löschen und dann alles aus Temp wieder da rein. Wichtig wäre A) das keine Foreign Key Einschränkungen das Löschen verhindern und B) müssten die Datensätze für das DISTINCT absolut gleich sein. Wenn sie es nicht sind müsstest du aggregieren oder so.
 
Wenn es keinen eindeutigen PK gibt der die Sätze doch irgendwie unterscheidet ist das nicht so banal.

Wäre es PG könnte man die CTID-Spalte verwenden:

Code:
est=*# select * from demo;
 i
---
 1
 1
 1
 2
 3
 4
 4
 4
 5
 5
 5
 6
 7
 7
 7
(15 rows)

test=*# select ctid,* from demo;
  ctid  | i
--------+---
 (0,1)  | 1
 (0,2)  | 1
 (0,3)  | 1
 (0,4)  | 2
 (0,5)  | 3
 (0,6)  | 4
 (0,7)  | 4
 (0,8)  | 4
 (0,9)  | 5
 (0,10) | 5
 (0,11) | 5
 (0,12) | 6
 (0,13) | 7
 (0,14) | 7
 (0,15) | 7
(15 rows)

test=*# select i, min(ctid) from demo group by i;
 i |  min   
---+--------
 3 | (0,5)
 5 | (0,9)
 4 | (0,6)
 6 | (0,12)
 2 | (0,4)
 7 | (0,13)
 1 | (0,1)
(7 rows)

test=*# select i from (select i, min(ctid) from demo group by i) bla;
 i
---
 3
 5
 4
 6
 2
 7
 1
(7 rows)

test=*#

Die CTID-Spalte ist eine systeminterne Spalte, die z.B. für Indexzugriffe genutzt wird.

Besser als das: es von vornherein vermeiden: jede Tabelle ein PK! Punkt.
 
Vielen Dank für eure Antworten. Dann werde ich wohl in den sauren Apfel beißen müssen und mit einer Hilfstabelle arbeiten müssen. Leider sind die Datensätze nicht gleich weshalb ich in der Tat aggregieren muß. Leider läßt sich das mit der eindeutigen Spalte nicht verhindern. Ich arbeite mit Tabellen aus unterschiedlichen Systemen von unterschiedlichen Autoren. Darauf habe ich keinen Einfluß.

Gruß
Andreas
 
Werbung:
Du kannst auch eine weitere Spalte erstellen, diese mit einer UID befüllen und hast dann einen Primärschlüssel.
 
Zurück
Oben