Lösche alle Datensätze, außer die letzen (neusten) 10.



  • Hallo Jungs,

    ich steh grad bischen aufn Schlauch. Ich hab ne Datenbanke mit chronologischen log einträgen, welche eienr UserID zugeordnet sind:

    Attribute: TimeStamp, UserID, Message

    Nun will ich alle Einträge bzw. Datensätze eine best. UserID (außer die 10 letzen neuen) löschen!

    Wie säche die SQL Query aus?

    Ungefähr so:

    (Select * from LogTable where UserID=1 Order by TimeStamp)

    jetzt hab ich die Datensätze in chronolgischer Reihenfolge des User 1! und will nun alles datensätze auser die 10 aktuellsten löschen!?!?

    Danke Grüße



  • Wenn deine DB das Attribut "top" versteht (z.B. MSSQL), dann z.B.

    delete * from LogTable
      where UserId = 1 and TimeStamp not in (select top 10 TimeStamp from LogTable where UserId = 1 order by TimeStamp)
    


  • DELETE * FROM `logTable` WHERE `UserId` = '1' HAVING COUNT (`UserId`) > 10 LIMIT 0, (COUNT (`UserId`) - 10) ORDER BY `TimeStamp`
    

    soll heißen

    LÖSCHE alle felder AUS logTabel BEI DENEN UserId GLEICH 1 WENN UserId MEHR ALS 10 mal VORKOMMT, BEGINNEND VON 0 BIS Anzahl der Ergebnisse MINUS 10, SORTIERE NACH TimeStamp
    

    Ist nur eine Idee, habs nicht getestet ..
    Bin mir gerade nicht mal sicher, ob man innerhalb einer Anfrage überhaupt subtrahieren darf .. ^^



  • Ich glaube nicht dass das auch nur annähernd gültiges SQL ist.
    Welcher Dialekt soll das sein?

    EDIT: Erklärung:
    Für HAVING braucht man normalerweise GROUP BY (WHERE filtert vor der Gruppierung, HAVING danach).
    Und den "LIMIT 0, (COUNT (`UserId`) - 10)" Teil check ich gar nicht. Wobei ich dazusagen muss dass ich LIMIT nie verwende, da ich nur mit MS-SQL arbeite (wo es kein LIMIT gibt, dafür aber TOP).



  • So müsste auch gehen (T-SQL):

    DECLARE @userId INT; -- ggf. Datentyp anpassen
    SET @userId = 1;
    
    DECLARE @threshold DATETIME; -- ggf. Datentyp anpassen
    SET @threshold = (
            SELECT MIN([TimeStamp]) FROM (
                SELECT TOP 10 [TimeStamp]
                FROM [LogTable]
                WHERE [UserId] = @userId ORDER BY [TimeStamp] DESC
            ) AS foo
        );
    
    DELETE [LogTable] WHERE [UserId] = @userId AND [TimeStamp] < @threshold;
    

    Die Version von Th69 müsste aber auch funktionieren.



  • hustbaer schrieb:

    Ich glaube nicht dass das auch nur annähernd gültiges SQL ist.
    Welcher Dialekt soll das sein?

    EDIT: Erklärung:
    Für HAVING braucht man normalerweise GROUP BY (WHERE filtert vor der Gruppierung, HAVING danach).
    Und den "LIMIT 0, (COUNT (`UserId`) - 10)" Teil check ich gar nicht. Wobei ich dazusagen muss dass ich LIMIT nie verwende, da ich nur mit MS-SQL arbeite (wo es kein LIMIT gibt, dafür aber TOP).

    LIMIT habe ich aus MySQL geklaut, der Rest sollte aber in jeder Subart existieren (also COUNT, HAVING, etc., bitte korrigieren falls nicht, sind aber IMO alle standardmäßig implentiert).
    Dass die Kombination einzelner Elemente aus meinem Vorschlag vllt. kein valides SQL darstellt, mag gut sein (hab mich länger nicht mehr damit befasst), ich denke aber schon. Es sollte auch nur ein Vorschlag sein (also meine Idee wie ich das Problem versuchen würde zu lösen) und keine Lösung 😉

    LIMIT beschränkt die Anzahl der Ergebnisse. "LIMIT x, y" bezeichnet die Startposition und die Anzahl der betroffenen Datensätze der Anfrage, es wird also ab dem x. Datensatz der SQL-Befehl angewandt. Die 2. Zahl nach dem Komma sagt, dass y Datensätze betroffen sein sollen (falls soviele vorhanden sind). Mit dem "COUNT (`UserId`) - 10" sollen alle Datensätze die dem User zugeordnet werden konnten gelöscht werden, außer die 10 letzten (ob die 10 letzten oder 10 ersten aus chronologischer Sicht hängt ja von der Sortierung der Anfrage ab).

    EDIT: an sich ist es besser meinen Vorschlag in mehrere Querys aufzuteilen, also einem SELECT und einem DELETE-Befehl, dann ließe sich das erstmal leichter durchblicken und wäre auch fehlerunanfälliger ^^



  • Danke Th69 , hat funktioniert;)


Anmelden zum Antworten