Encoder: Abfrage für Datenbereinigung gesucht

Tagchen!

Ich habe eine Aufgabe, zu der ich keine passende Lösung in SQL hin kriege. Vielleicht kann mir ja jemand auf die Sprünge helfen.

Meine Tabelle enthält ein Datum und eine zugehörige Gesamtleistung. Die Leistung nimmer immer zu, also bei größerem Datum ist auch der Wert größer.
Jetzt will ich diese Tabelle ausdünnen, d.h. Einträge entfernen bei denen sich die Leistung im Vergleich zum vorigen Wert nicht oder nur kaum geändert hat.
Ich gebe z.B. die Toleranz 2 vor. In der folgenden Tabelle soll demnach alles rausfliegen, wo sich ein Wert im Vergleich zum vorigen Wert um höchstens 2 ändert.

Datum | Wert
1 | 10
2 | 11 (raus)
3 | 12 (raus)
4 | 13 (bleibt, da zwischen 13 und der übrig gebliebenen 10 mehr als 2 ist)
5 | 17
6 | 23
7 | 25 (raus)
8 | 26
9 | 29

Man beachte: Nicht die Differenz zum absolut vorigen Wert soll zählen, sondern die zum übrig bleibenden vorigen Wert! Wenn sich also alles um nur 1 erhöht, sollen trotzdem Einträge drin bleiben.

Mir will aber kein SQL Statement einfallen, das so etwas kann. Meine Lösung besteht bisher darin, ein Programm auf die DB loszulassen, das die Einträge einliest und dann alles durchläuft und einzeln löscht.

  1. Hello,

    Man beachte: Nicht die Differenz zum absolut vorigen Wert soll zählen, sondern die zum übrig bleibenden vorigen Wert! Wenn sich also alles um nur 1 erhöht, sollen trotzdem Einträge drin bleiben.

    Mir will aber kein SQL Statement einfallen, das so etwas kann. Meine Lösung besteht bisher darin, ein Programm auf die DB loszulassen, das die Einträge einliest und dann alles durchläuft und einzeln löscht.

    In solchen Fällen helfen meistens benutzerdefinierte Variablen.
    http://dev.mysql.com/doc/refman/5.1/en/user-variables.html

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de
  2. Hi,

    Man beachte: Nicht die Differenz zum absolut vorigen Wert soll zählen, sondern die zum übrig bleibenden vorigen Wert! Wenn sich also alles um nur 1 erhöht, sollen trotzdem Einträge drin bleiben.

    Hmm...

      
    DELETE FROM tabelle  
    WHERE wert < (SELECT 2+MAX(t.wert) FROM tabelle t WHERE t.datum < tabelle.datum)  
    ORDER BY tabelle.datum  
    
    

    Lösche alle Einträge aus deiner tabelle,
    deren Wert als der größte ältere Eintrag aus der Tabelle (hier nutze ich die monotone Steigung aus!). Das Löschen geschieht durch ORDER BY in der Reihenfolge des Datums, damit ich zuerst die alten lösche (für MySQL siehe etwa DELETE-Syntax).

    Wichtig: ist der Eintrag der erste, ist die Unterabfrage NULL, und der erste Eintrag wird nicht gelöscht (weil wert < NULLzu FALSE evaluiert wird.

    Bis die Tage,
    Matti

    1. Hallo,

      Wichtig: ist der Eintrag der erste, ist die Unterabfrage NULL, und der erste Eintrag wird nicht gelöscht (weil wert < NULLzu FALSE evaluiert wird.

      genauer: weil wert < NULL zu NULL evaluiert wird, NULL nicht TRUE ist und somit die WHERE-Bedingung nicht auf den ersten Datensatz zutrifft.

      Das mag sich nach Haarspalterei anhören, aber der Umgang mit NULL-Werten ist eine große Hürde für SQL-Neulinge.

      Freundliche Grüße

      Vinzenz

    2. Da heißt es "Currently, you cannot delete from a table and select from the same table in a subquery."
      Man bräuchte schon ziemlich Vertrauen in die Funktion der Datenbank, um das laufen zu lassen :-)
      Ich denke ich lass es dabei dass ich einfach wirklich alle Datensätze der Reihe nach durchgehe. Auch wenns nicht sehr performant ist, aber das zugehörige Script kann ja immer wieder mal angestoßen werden.

      1. Na dann kopier doch die Tabelle mal (physikalisch) mit SELECT INTO ... oder so. Es ist ja eh nur für einen begrenzten Zeitraum (so lang wie die Datenbereinigung läuft) .. damit solltest du das subquery Problem umgehen können. Indizes auf die kopierte Tabelle packen - das muss ich nicht extra erwähnen?

        Ciao, Frank