MysQL - DELETE ab dem x-ten Eintrag pro ID
Honda
- datenbank
Hallo,
ich habe in einer MySQL-Datenbank eine Reihe von Einträgen pro ID, mit Datumsangabe.
D.h. >> ID, Eintrag, Datum
Wie gehe ich nun vor, wenn ich alle über den 10ten Eintrag (sortiert nach Datum) hinausgehenden Einträge pro ID löschen möchte?
D.h. als Resultat soll gewährleistet sein, dass pro ID stets maximal 10 Einträge vorhanden sind (sortiert nach Datum).
Vielen Dank,
Honda
Hallo!
D.h. >> ID, Eintrag, Datum
Wie gehe ich nun vor, wenn ich alle über den 10ten Eintrag (sortiert nach Datum) hinausgehenden Einträge pro ID löschen möchte?
D.h. als Resultat soll gewährleistet sein, dass pro ID stets maximal 10 Einträge vorhanden sind (sortiert nach Datum).
Das ganze geht IMHO nur mit einem Subselect.
Mit dem Subselect hole ich das Datum des 11. Eintrages mit der id=10, absteigent sortiert. Dann werden die Einträge gelöscht, die die id=10 besitzen und bei denen das Datum kleiner oder gleich ist, als das vom 11. Eintrag. Der 11. Eintrag sollte also auch mit raus fliegen.
!!! UNGETESTET !!!
DELETE
FROM
tabelle
WHERE
id = 10
AND
datum <=
(
SELECT datum FROM tabelle WHERE id = 10 ORDER BY datum DESC LIMIT 10, 1
);
André Laugks
Hallo André
Wie gehe ich nun vor, wenn ich alle über den 10ten Eintrag (sortiert nach Datum) hinausgehenden Einträge pro ID löschen möchte?
D.h. als Resultat soll gewährleistet sein, dass pro ID stets maximal 10 Einträge vorhanden sind (sortiert nach Datum).
Das ganze geht IMHO nur mit einem Subselect.
Nein. Da liegst Du falsch.
Mit dem Subselect hole ich das Datum des 11. Eintrages mit der id=10, absteigent sortiert. Dann werden die Einträge gelöscht, die die id=10 besitzen und bei denen das Datum kleiner oder gleich ist, als das vom 11. Eintrag. Der 11. Eintrag sollte also auch mit raus fliegen.
!!! UNGETESTET !!!
und ungeeignet.
DELETE
FROM
tabelle
WHERE
id = 10
AND
datum <=
(
SELECT datum FROM tabelle WHERE id = 10 ORDER BY datum DESC LIMIT 10, 1
);
Dummerweise haben die nächsten 5 Datensätze ebenfalls das gleiche Datum wie der 11. Eintrag. Es bleiben nur noch 5 Datensätze übrig, keine 10 wie gefordert.
Wenn schon Subselect, dann finde eine Spalte, die die 10 Datensätze, die übrig bleiben sollen genau identifiziert und verwende `WHERE ... NOT IN (SELECT ...)`{:.language-sql}.
Eine Möglichkeit ohne Subselect wäre der Einsatz von Benutzervariablen. Siehe mein [Archivposting](/archiv/2006/9/t136068/#m883458) in einem anderen Zusammenhang. Lösche die Datensätze mit Variablenwerten > 10. (Ebenfalls ungetestet!)
Freundliche Grüße
Vinzenz
Moin!
Das ganze geht IMHO nur mit einem Subselect.
Nein. Da liegst Du falsch.
Schön, dass die Ideen so eindeutig richtig oder falsch zu sein scheinen. :)
DELETE
FROM
tabelle
WHERE
id = 10
AND
datum <=
(
SELECT datum FROM tabelle WHERE id = 10 ORDER BY datum DESC LIMIT 10, 1
);
>
> Dummerweise haben die nächsten 5 Datensätze ebenfalls das gleiche Datum wie der 11. Eintrag. Es bleiben nur noch 5 Datensätze übrig, keine 10 wie gefordert.
MySQL hat auch in Version 5.1 die Einschränkung, dass man kein Subselect auf die Tabelle machen kann, aus der man löschen will. Insofern funktioniert der Ansatz ohnehin nicht.
> Wenn schon Subselect, dann finde eine Spalte, die die 10 Datensätze, die übrig bleiben sollen genau identifiziert und verwende `WHERE ... NOT IN (SELECT ...)`{:.language-sql}.
Auch dein Ansatz übrigens nicht.
Aber es gibt eine recht simple Methode: DELETE kann ORDER BY und LIMIT.
Dabei ist jetzt allerdings die genaue Fragestellung zu berücksichtigen: Der OP hat gefordert, dass \_maximal\_ 10 Datensätze übrig bleiben. Damit ist die Aufgabe unterspezifiziert, denn auch 0 Datensätze wären ja \_maximal\_ 10, was die Löschaufgabe erheblich vereinfachen würde, aber aus nachvollziehbaren Gründen kaum sinnvoll erscheint.
- Sven Rautenberg
--
"Love your nation - respect the others."
hi,
Aber es gibt eine recht simple Methode: DELETE kann ORDER BY und LIMIT.
Auch in der von SELECT "bekannten Form"?
Wenn ich das Manual diesbezüglich richtig verstehe, kann man bei DELETE mittels LIMIT nur einen "row_count" angeben - wie viele Datensätze maximal gelöscht werden sollen. Aber einen Offset anzugeben wie bei einem SELECT, geht da nicht.
In Kombination mit ORDER BY kann man da also problemlos sagen "lösche mir die X ältesten Datensätze".
Aber "lösche alle bis auf die X letzten" ist damit nicht in einem simplen DELETE-Statement möglich.
gruß,
wahsaga