Sql - doppelte Daten finden & einmal löschen

Hallo liebe Experten,

ich versuche gerade eine Datenbank aufzuräumen und dazu wollte ich mit einem Befehl doppelte (identische) Einträge löschen.
Das Problem ist nur, dass ich das nicht hinbekomme…
Ich dachte mir, dass ich einfach gruppiere, zähle und dann lösche…
Aber wenn ich ein SQL Statement mit count und group kombiniere, dann erhalte ich ein
#1111 - Invalid use of group function
sobald ich das count in die WHERE Klausel setze…
Mache ich etwas falsch? Oder muss ich wirklich auch alles zurückgeben lassen? Lösbar ist es sicher auch so - aber ich hätte halt gerne eine einfache und schöne lösung für das Problem :smile:

Vielen Dank
Munich

Mahlzeit,

ich versuche gerade eine Datenbank aufzuräumen und dazu wollte
ich mit einem Befehl doppelte (identische) Einträge löschen.
Das Problem ist nur, dass ich das nicht hinbekomme…
Ich dachte mir, dass ich einfach gruppiere, zähle und dann
lösche…

Genau:

Select a, b, c, d, e from Tabelle group by a, b, c, d, e having count(*) > 1;

Aber wenn ich ein SQL Statement mit count und group
kombiniere, dann erhalte ich ein
#1111 - Invalid use of group function

Daraus ersehe ich: Du arbeitest mit MySQL, right?

Mache ich etwas falsch? Oder muss ich wirklich auch alles
zurückgeben lassen? Lösbar ist es sicher auch so - aber ich
hätte halt gerne eine einfache und schöne lösung für das
Problem :smile:

Das Problem ist nicht ganz so trivial. Wenn die Datensätze absolut identisch sind, ist es schwierig.

Hast Du ein Feld, bei dem die Datensätze sich doch voneinander unterscheiden (z.B. eine Satz_ID o.Ä.), kannst Du das dadurch lösen, daß Du auf diese abzielst:

delete 
 from Tabelle 
 where (a, b, c, d, e, satz\_id) in (
 select a, b, c, d, e, max(satz\_id)
 from Tabelle
 group by a, b, c, d, e
 having count(\*) \> 1);

Ansonsten bleibt nur der Weg, eine solche identifizierende Spalte hinzuzufügen (z.B. über einen AutoIncrement), die Datensätze wie oben beschrieben löschen und die Spalte wieder zu entfernen.

Gruß

Sancho

Select a, b, c, d, e from Tabelle group by a, b, c, d, e
having count(*) > 1;

ahhh super!
Das „having“ kannte ich noch nicht. da muss ich mal drüber nachlesen :smile:

Daraus ersehe ich: Du arbeitest mit MySQL, right?

richtig :smile:
°oO( wäre das von Relevanz gewesen? )

Hast Du ein Feld, bei dem die Datensätze sich doch voneinander
unterscheiden (z.B. eine Satz_ID o.Ä.), kannst Du das dadurch
lösen, daß Du auf diese abzielst:

nein, hab ich leider nicht… eigentlich auch ganz bewusst drauf verzichtet - aber durch irgendwelche Scriptfehler oder F5-Dinger, die ich nicht abgecheckt hab hab ich wohl nun doch doubletten in der Datenbank… Und die verursachen wiederum Probleme :-/

Ansonsten bleibt nur der Weg, eine solche identifizierende
Spalte hinzuzufügen (z.B. über einen AutoIncrement), die
Datensätze wie oben beschrieben löschen und die Spalte wieder
zu entfernen.

hmmm… aber kann ich nicht auch mit Limit 1 arbeiten um das ganze zu bereinigen? So, dass ich immer nur einen Datensatz von beiden lösche?

Vielen Dank jedenfalls schon mal!
Grüße
Munich

Mahlzeit,

ahhh super!
Das „having“ kannte ich noch nicht. da muss ich mal drüber
nachlesen :smile:

Das Having ist sozusagen ein Where, das sich auf die gruppierten Ergebnisse bezieht.

richtig :smile:
°oO( wäre das von Relevanz gewesen? )

Ja. Bei Oracle z.B. hast Du eine Pseudospalte ROWID, die hier ganz hervorragend helfen würde.

nein, hab ich leider nicht… eigentlich auch ganz bewusst
drauf verzichtet - aber durch irgendwelche Scriptfehler oder
F5-Dinger, die ich nicht abgecheckt hab hab ich wohl nun doch
doubletten in der Datenbank… Und die verursachen wiederum
Probleme :-/

Ich würde dringend dazu raten, jeden Datensatz eindeutig zu identifizieren. Du siehst, es bringt was :smile:

hmmm… aber kann ich nicht auch mit Limit 1 arbeiten um das
ganze zu bereinigen? So, dass ich immer nur einen Datensatz
von beiden lösche?

Ich kenne mich mit MySQL nicht so gut aus (Limit kennt Oracle nicht), aber so, wie ich es verstehe, würde das nicht funktionieren - Du willst nicht „eine Zeile“ löschen, sondern „die erste“ von jedem Pärchen.

Wenn Du den Kram über die Zusatzspalte machst, dann logischerweise auf einer Backup-Tabelle!

Gruß

Sancho

1 Like

hihi Mahlzeit :smile:

Das Having ist sozusagen ein Where, das sich auf die
gruppierten Ergebnisse bezieht.

vielen Dank auch für diese Info…
wird mir denke ich noch gute Dienste tun.
Weisst Du zufällig noch, ob das in Access genauso funktioniert? Zumindest gibts da ja auch eine SQL Ansicht, wo man das reinschreiben könnte… Automatisch benutzt er soweit ich weiss aber immer nur WHERE…

richtig :smile:
°oO( wäre das von Relevanz gewesen? )

Ja. Bei Oracle z.B. hast Du eine Pseudospalte ROWID, die hier
ganz hervorragend helfen würde.

und wieder was gelernt… Naja - aber mit Oracle hab ich (leider?) noch nicht gearbeitet… Wenn ich mit php da leicht drauf verbinden könnte wäre es ne überlegung wert *g*

Ich würde dringend dazu raten, jeden Datensatz eindeutig zu
identifizieren. Du siehst, es bringt was :smile:

normalerweise mache ich das auch…
aber naja - in der Datenbank hatte ich es eigentlich für unnötig gehalten :-/
Aber man irrt sich eben öfter als man es Wahr haben will…

hmmm… aber kann ich nicht auch mit Limit 1 arbeiten um das
ganze zu bereinigen? So, dass ich immer nur einen Datensatz
von beiden lösche?

Ich kenne mich mit MySQL nicht so gut aus (Limit kennt Oracle
nicht), aber so, wie ich es verstehe, würde das nicht
funktionieren - Du willst nicht „eine Zeile“ löschen, sondern
„die erste“ von jedem Pärchen.

naja - ich arbeite wie ich gerade schon geschrieben habe mit php - damit könnte ich dann eben so viele löschen, wie eben zu viel sind.
Ich denke, dass es so gehen wird… aber ich muss es erst mal testen… :smile:

Wenn Du den Kram über die Zusatzspalte machst, dann
logischerweise auf einer Backup-Tabelle!

testen tu ich’s eh lokal…
Und erst wenn es funktioniert lad’ ich die Datei auf den „Live“-Server hoch :smile:

Viele Grüße
Munich

Weisst Du zufällig noch, ob das in Access genauso
funktioniert? Zumindest gibts da ja auch eine SQL Ansicht, wo
man das reinschreiben könnte… Automatisch benutzt er soweit
ich weiss aber immer nur WHERE…

Nö, funktioniert genauso.

naja - ich arbeite wie ich gerade schon geschrieben habe mit
php - damit könnte ich dann eben so viele löschen, wie eben zu
viel sind.
Ich denke, dass es so gehen wird… aber ich muss es erst mal
testen… :smile:

Ich habe nicht verstanden, wie Du es machen willst, aber ich fürchte, so leicht geht das nicht.

Mit PHP und Oracle geht das hervorragend, ich habe da meine eigene kleine Anwendung, die einwandfrei funktioniert.

Gruß

Sancho

Nö, funktioniert genauso.

klasse! :smile: das könnte vielleicht noch weitere Abfragen erleichtern in nächster Zukunft :smile:

Ich habe nicht verstanden, wie Du es machen willst, aber ich
fürchte, so leicht geht das nicht.

doch doch… hab es schon hinbekommen und es funktioniert ganz toll :smile:
hier der code

function cleanup()
 {
 $sql = "SELECT \*, count(\*) as counter FROM $tabelle group by dies, das, jenes, sonstiges having count(\*) \> 1";
 $query = mysql\_query($sql);
 while ($result = mysql\_fetch\_array($query))
 {
 $v1 = $result[0];
 $v2 = $result[1];
 $v3 = $result[2];
 $v4 = $result[3];
 $limit = $result['counter'] - 1;
 $nextsql = "DELETE FROM $tabelle WHERE dies='$v1' AND das='$v2' AND jenes='$v3' AND sonstiges='$v4' LIMIT $limit";
 mysql\_query($nextsql) or die("Fehler in sql: 
\n$nextsql");
 }
 }

vielen Dank nochmal für alles *smile*