NiX: MySQL: Alles löschen ausser...

Hallo zusammen.

Ich möchte aus einer MySQL Tabelle alles löschen lassen ausser die 20 aktuellsten Einträge. (Die Tabelle hätte eine vorlaufende ID)

Kann mir jemand sagen, wie ich das mache?

Danke und Gruss,
NiX

  1. Ich möchte aus einer MySQL Tabelle alles löschen lassen ausser die 20 aktuellsten Einträge. (Die Tabelle hätte eine vorlaufende ID)

    Kann mir jemand sagen, wie ich das mache?

    Beispiel:
    DELETE FROM
     Table1
    WHERE
     (
     Table1.ID
     NOT IN
      (
      SELECT <LIMIT-Klausel>
       Table1.ID
      FROM
       Table1
      ORDER BY
       Table1.ID DESC
      )
     )

    Die nur skizzierte LIMIT-Klausel muesstest Du anpassen, ebenso die Tabellennamen und Datenfeldnamen.

    Prinzip verstanden?

    1. yo,

      Die nur skizzierte LIMIT-Klausel muesstest Du anpassen, ebenso die Tabellennamen und Datenfeldnamen.

      die LIMIT klausel gehört nach der Order BY klausel ans ende der unterabfrage. außerdem ist die id spalte keine gute idee, um die 20 aktuellsten datensätze zu bekommen, sondern dafür muss schon eine spalte mit datum, bzw. uhrzeit herhalten oder was auch immer mit aktuellsten gemeint ist. die id kann man dafür nicht benutzen.

      Ilja

      1. die LIMIT klausel gehört nach der Order BY klausel ans ende der unterabfrage. außerdem ist die id spalte keine gute idee, um die 20 aktuellsten datensätze zu bekommen, sondern dafür muss schon eine spalte mit datum, bzw. uhrzeit herhalten oder was auch immer mit aktuellsten gemeint ist. die id kann man dafür nicht benutzen.

        Mmh, hat was.

        DELETE FROM chat
          WHERE ( chat.ID
            NOT IN (
              SELECT chat.ID FROM chat
                ORDER BY chat.time DESC LIMIT 0,20 ))

        Ausgabe:

        #1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'

        Kannst du mir helfen?

        Danke und Gruss,
        NiX

        1. yo,

          #1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'

          Kannst du mir helfen?

          nun welche version hast du den ? und ja, man könnte es ein wenig ummodeln, wobei es dann aber mehr als zwanzig detensätze seien können, nämlich genau dann, wenn zufällig das datum des 20ten datensatz auf mehrere datensätze zutrifft.

          DELETE FROM chat
          WHERE chat.time <
            (
             SELECT MIN(chat.time)
             FROM chat
             ORDER BY chat.time DESC
             LIMIT 0,20
            )

          aber immer erst als SELECT abfrage versuchen, ob auch die richtigen datensätze getroffen sind, bevor man dann löscht. ;-)

          Ilja

          1. nun welche version hast du den ?

            5.0.22-Debian_4-log

            wenn zufällig das datum des 20ten datensatz auf mehrere datensätze zutrifft.

            Das würde nicht in dem Fall viel machen, wäre eh ein Zufall.

            DELETE FROM chat
            WHERE chat.time <
              (
               SELECT MIN(chat.time)
               FROM chat
               ORDER BY chat.time DESC
               LIMIT 0,20
              )

            #1093 - You can't specify target table 'chat' for update in FROM clause

            Erzeigt noch MIN irgendwie rot an??

            Gruss,
            NiX

            1. #1093 - You can't specify target table 'chat' for update in FROM clause

              Erzeigt noch MIN irgendwie rot an??

              Kannst Du denn auf "chat" ueberhaupt ein UPDATE ausfuehren? Was kriegst Du als Ergebnis auf das innere SELECT?

              1. Kannst Du denn auf "chat" ueberhaupt ein UPDATE ausfuehren? Was kriegst Du als Ergebnis auf das innere SELECT?

                Das innere Select stimmt schon, wenn ich nur das ausführe gehts.
                Ich habe es jetzt anders gemacht.
                Ich lese zuerst per PHP das SELECT, werte das aus und führe gemäss dem dann ein von PHP kreiirtes DELETE aus.
                Ist sicher nicht die schönste Lösung, aber sie geht ;-)

                Gruss,
                NiX

            2. yo,

              #1093 - You can't specify target table 'chat' for update in FROM clause

              ok, das geht auch nicht, war mein fehler. das dbms sperrt sich bei der unterabfrage, da zieldatenbank und quelldatenbank der abfrage die gleiche ist. eventuell müsste man doch zwei anweisungen draus machen und die tabelle für die löschung kurzfristig für änderungen sperren.

              eigentlich wäre der eleganteste weg, das wirklich über

              DELETE FROM tabelle ORDBY by time DESC LIMIT 20 zu machen.

              in der doku zu 5.0 steht es jedenfalls so da.

              < http://dev.mysql.com/doc/refman/5.0/en/delete.html>

              Ilja

              1. Hi,

                DELETE FROM tabelle ORDER BY by time DESC LIMIT 20

                würde doch die 20 neuesten löschen.
                Also das genaue Gegenteil dessen, was gewünscht ist.

                Müßte es nicht
                DELETE FROM tabelle ORDER BY by time DESC LIMIT 21,999999999
                sein (ggf. noch ne höhere Nummer für das obere Limit nehmen ...)?

                cu,
                Andreas

                --
                Warum nennt sich Andreas hier MudGuard?
                Schreinerei Waechter
                O o ostern ...
                Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
              2. yo,

                meine anweisung war natürlich quatsch, da habe ich doch die daten gelöscht, die übrig bleiben sollen...

                Ilja

                1. Hi,

                  meine anweisung war natürlich quatsch, da habe ich doch die daten gelöscht, die übrig bleiben sollen...

                  Zu spät ...

                  cu,
                  Andreas

                  --
                  Warum nennt sich Andreas hier MudGuard?
                  Schreinerei Waechter
                  O o ostern ...
                  Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
      2. ... außerdem ist die id spalte keine gute idee, um die 20 aktuellsten datensätze zu bekommen, sondern dafür muss schon eine spalte mit datum, bzw. uhrzeit herhalten oder was auch immer mit aktuellsten gemeint ist. die id kann man dafür nicht benutzen.

        Warum nicht? Ist die ID ein auto increment-Wert vom Typ integer, so kann man zwar nicht sicher sein, dass diese fortlaufend ist (je nach RDBMS :), aber doch, dass die zuletzt generierte ID einen groesseren Wert besitzt ist als die vorher generierten. (Was du vorschlaegst ist ueber einen Zeitstempel bspw. die zuletzt geaenderten Datensaetze nicht zu loeschen.)

        1. yo,

          Warum nicht? Ist die ID ein auto increment-Wert vom Typ integer, so kann man zwar nicht sicher sein, dass diese fortlaufend ist (je nach RDBMS :), aber doch, dass die zuletzt generierte ID einen groesseren Wert besitzt ist als die vorher generierten.

          ich für meinen teil würde mich darauf nicht verlassen, zumal es auch gar nicht notwendig ist. und spätestens, wenn ein datensatz aktualisiert wird (update) bleibt die id gleich, die aktualisierung aber nicht.

          Ilja

          1. ich für meinen teil würde mich darauf nicht verlassen, zumal es auch gar nicht notwendig ist. und spätestens, wenn ein datensatz aktualisiert wird (update) bleibt die id gleich, die aktualisierung aber nicht.

            Der Fragesteller will vermutlich nur ¨1.) in eine Tabelle Datensaetze einfuegen und 2.) in einem weiteren Vorgang zuletzt eingefuegte _nicht_ loeschen. Was Du vorschlaegst ist zwar sympatisch und grundsaetzlich die richtige Vorgehensweise, ABER Du siehst ja was rauskommt, wenn es nicht "idiotensicher" (sorry an dieser Stelle fuer den Gebrauch dieses boesen Worts! btw, nichts ist wirklich idiotensicher, denn Idioten haben Phantasie.) serviert wird.

    2. Prinzip verstanden?

      Ja, perfekt.
      Herzlichen Dank!

  2. Hi,

    wäre doch auch so möglich, oder?

    $result=mysql_query("SELECT COUNT(*) AS anzahl FROM tabelle");
    $anzahl=mysql_fetch_array($result);
    $grenze=$anzahl-20;

    $result1=mysql_db_query("SELECT * FROM tabelle");
    $row = mysql_fetch_array($result1);
    $id = $row["id"];

    while ($id <= $grenze)
    {
    DELETE * from tabelle where id = $id;
    $id++;
    }

    Hallo zusammen.

    Ich möchte aus einer MySQL Tabelle alles löschen lassen ausser die 20 aktuellsten Einträge. (Die Tabelle hätte eine vorlaufende ID)

    Kann mir jemand sagen, wie ich das mache?

    Danke und Gruss,
    NiX

    1. wäre doch auch so möglich, oder?

      $result=mysql_query("SELECT COUNT(*) AS anzahl FROM tabelle");
      $anzahl=mysql_fetch_array($result);
      $grenze=$anzahl-20;

      $result1=mysql_db_query("SELECT * FROM tabelle");
      $row = mysql_fetch_array($result1);
      $id = $row["id"];

      while ($id <= $grenze)
      {
      DELETE * from tabelle where id = $id;
      $id++;
      }

      Zu Deinem Pseudo-Code: zu viele SQL-Statements, das ist uncool.
      Aber grundsaetzlich¨richtig.
      :)

    2. Hallo,

      DELETE * from tabelle where id = $id;

      Da du mit DELETE keine einzelnen Spalten lössten kannst, ist der Stern im Query überflüssig bzw. falsch und ergibt eine Fehlermeldung.

      Außerdem ist es grundsätzlich keine gute Idee in Schleifen Querys auszuführen - auch hier ist es völlig überflüssig - deine Schleife lässt sich problemlos durch einen Query ersetzen:
      DELETE FROM tabelle WHERE id IN (implode(',',range($id,$grenze)))
      (dass es Unsinn ist für die Lösung des Problems 3 (oder mehr) Querys abzufeuern, sei mal außen vor gelassen)

      Grüße aus Nürnberg
      Tobias

      --
      TOP7: Hinweise, dass du wieder keinen Nobel-Preis bekommst
      Selfcode: sh:( fo:) ch:? rl:| br:< n4:& ie:% mo:| va:) de:] zu:) fl:( ss:) ls:[ js:|