Encoder: Daten in Intervallen abfragen

Hallo ihr
(DB: MySql)

Ich habe Daten vorliegen, Werte die mit einem Zeitstempel versehen sind. Die möchte ich abfragen.
Dabei reicht es mir wenn ich nur immer die letzten Werte auslese, die zum vorigen einen bestimmten Maximalabstand haben. Z.B. 10 Minuten.
Es wird also ein Wert ausgegeben. Dann werden alle weiteren Werte so lange übersprungen, bis der letzte Wert gefunden wird der weniger als 10 Minuten vom ausgegebenen Wert entfernt ist. Dieser wird dann wieder ausgegeben.
Wenns unter 10 Minuten keinen gibt, soll eben der nächste verfügbare verwendet werden.

Zum Beispiel werden etwa minütlich Stückzahlen eingetragen. Mir reichts aber wenn ich den Stand alle 10 Minuten habe.

Bisher mache ich das programmtechnisch. Wär aber schon schöner wenn ich das gleich so auslesen könnte. Nur hab ich keine Idee wie.
Kann mir da jemand helfen?

Ich dachte schon an GROUP BY und gruppiert wird dann nach der Zeit geteilt durch 10 Minuten. Aber vielleicht gibts da ja noch was schöneres.
Kann ich irgendwie eine Zeile der Abfrage auf eine vorhergehende beziehen?

  1. Lieber Encoder,

    hilft Dir das Stichwort "SELF JOIN" weiter?

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
  2. Hi,

    Kann ich irgendwie eine Zeile der Abfrage auf eine vorhergehende beziehen?

    Theoretisch ja, mit User-Defined Variables – aber dabei gilt zu beachten, was dort zum Zuweisen eines Wertes an eine Variable und Auslesen des Wertes im selben Statement beschrieben steht.

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
  3. Hi,

    willst du ein Sliding oder Hopping Window ... Sliding Window wäre an der Stelle gleichzusetzen mit einem Moving Average. Dafür ist im Normalfall ein Self Join notwendig.

    Ein Hopping Window ist dagegen ein Segment(t) aus einer Serie welches nach Segment(t-1) beginnt und vor Segment(t+1) aufhört. Mit 10 Minuten beschreibst du lediglich die grösse des Windows aber du brauchst noch einen Startpunkt. Daraus konstruierst du dann eine Serie von Ranges und diese joinst du dann auf deine Daten anhand deren Zeitstempel.

    Gruss aus der Kararibik
    Frank

    1. Hallo
      Ich hab mir eure Tips durchdacht, komme aber nicht wirklich weiter.
      Wenn ich alles auslese, könnte ich per Code das folgende tun:
      aktuell = liste[0];
      for (i = 1; i < count(liste); i++)
      {
        if (liste[i].Datum >= (aktuell.Datum + 10 Minuten)
        {
          liste[i] zu Ergebnis hinzufügen
          aktuell = liste[i];
        }
      }

      Dieses Ergebnis wäre mir am liebsten. Alles überspringen, was "zu nahe" am letzten Datensatz liegt.

      Variablen kenne ich in SQL. Aber in diesem Fall bringe ich die da nicht mit hinein.
      Den Selfjoin kenne ich auch, aber auch hier fehlt mir der richtige Gedanke.

      Ich müsste ja ausdrücken "nimm den Wert nur dann, wenn sein Datum mindestens 10 Minuten später liegt als das Datum des vorigen Werts". Irgendwie im WHERE steht dann die Bedingung mit den 10 Minuten? Damit die Werte bereits bei der Auswertung des WHERE die richtige Reihenfolge haben, müssten sie schon vor der Durchsuchung in der richtigen Sortierung angefasst werden, das krieg ich auch schon nicht formuliert.
      Und wie ich dann den Bezug zum zuletzt ausgewählten Wert herstelle weiß ich auch nicht.

      1. Tach!

        Ich müsste ja ausdrücken "nimm den Wert nur dann, wenn sein Datum mindestens 10 Minuten später liegt als das Datum des vorigen Werts".

        Stored Procedure wäre meine erste Idee eines Lösungsansatzes.

        Irgendwie im WHERE steht dann die Bedingung mit den 10 Minuten? Damit die Werte bereits bei der Auswertung des WHERE die richtige Reihenfolge haben, müssten sie schon vor der Durchsuchung in der richtigen Sortierung angefasst werden, das krieg ich auch schon nicht formuliert.

        Das geht auch nicht so einfach. Sortiert wird erst nach der Datensatzauswahl. WHERE läuft also auf unsortierten Daten. Vielleicht wird ein Index verwendet, um die Daten schneller zu finden, aber das ist auch nicht gewiss und hängt von diversen Faktoren ab - manchmal ist ein Full Table Scan schneller als eine Indexverwendung.

        Und wie ich dann den Bezug zum zuletzt ausgewählten Wert herstelle weiß ich auch nicht.

        Einen Cursor über die sortierte aber uneingeschränkte Menge laufen lassen, mithilfe von Variablen die guten in ein temporäres Töpfchen legen und dieses am Ende der S.P. ausgeben.

        dedlfix.

      2. Servus,

        gegeben sein ein Tabellenschema ... ich verwende mal T-SQL fuer Microsofts SQL Server ... Datentypen sind dann ggf nach mySql zu uebersetzen

          
        CREATE TABLE T1 (  
          ID int not null identity(1,1) primar key clustered,  
          Menge int not null default (0),  
          TmStamp datetime not null default (CURRENT_TIMESTAMP)  
        )  
        
        

        Daten waeren dann in etwa so
        ID       Menge              TmStmp
        ------------------------------------------------------------------
        1        1                       10:00:01.123
        2        3                       10:00:07.123
        3        2                       10:02:08.123
        4        2                       10:04:01.123
        5        3                       10:05:06.666
        6        4                       10:08:01.777
        7        3                       10:12:01.123
        8        4                       10:14:02.666

        Um jetzt ein Moving Average oder Moving Sum zu bekommen

          
        SELECT a.Id, a.TmStmp, SUM(b.Menge) AS MovingSum, Min(b.TmStmp) AS SampleBegin, Max(b.TmStmp) AS SampleEnd, COUNT(b.Id) AS CountSamples  
          FROM T1 a  
          INNER JOIN T1 b ON b.TmStmp <= a.TmStamp   -- alternatively DATEDIFF(s, b.TmStmp, a.TmStmp) BETWEEN 0 AND 600  
          WHERE DATEDIFF(s, b.TmStmp, a.TmStmp) BETWEEN 0 AND 600  
          GROUP BY a.Id, a.TmStmp  
          ORDER BY a.Id  
        
        

        Und diese Ergebnisse kannst du dann filtern mit einem beliebigen Datum/Zeit als Parameter und einem ORDER BY TmStmp DESC und LIMIT 1 ...

        So schwer war's doch nich, oder?

        Ciao und Gruss aus der Kararibik, Frank