Encoder: Summenbildung in Gruppen

Hallo Experten für Kniffeleien :-)

Ich hab wieder was das mir schwerfällt zu beschreiben.
Und zwar stelle man sich der Einfachheit halber Maschinen vor, zu denen in nicht beeinflussbaren Intervallen Stückzahlen abgerufen und in einer Tabelle gespeichert werden. Die Stückzahlen summieren sich auf.
Als Beispiel

Maschine A - 00:00 - 5
Maschine A - 00:10 - 7
Maschine B - 00:12 - 3
Maschine C - 00:16 - 4
Maschine A - 00:27 - 12
Maschine C - 00:28 - 8
Maschine B - 00:30 - 9
usw.

Mehrere Maschinen können zusammengehören, sagen wir A und C.
Was ich jetzt haben möchte ist eine Liste aller Zeitpunkte von A und C, mit der jeweiligen Gesamtsumme.

Also das hier
00:00 - Gruppe AC - 5
00:10 - Gruppe AC - 7
00:12 - Gruppe B  - 3
00:16 - Gruppe AC - 11 (nämlich die letzten 7 von A und die aktuellen 4 von C)
00:27 - Gruppe AC - 16
00:28 - Gruppe AC - 20 (die letzten 12 von A und die aktuellen von C)
00:30 - Gruppe B  - 9

Mit der Summierung hab ich ein Problem. Ich weiß nicht ob das per SQL geht und auch als Code hab ich bisher nur ziemlich wilde Konstrukte im Kopf. Wenns einfacher geht wär schön.
Hat da jemand einen Ansatz?

DB ist übrigens MySql, falls da mir da doch irgendwas brauchbares entgangen ist.

  1. hi,

    DB ist übrigens MySql, falls da mir da doch irgendwas brauchbares entgangen ist.

    Brauchbar ist evntl.
    WITH ROLLUP

    Schönes WE,
    Hotti

  2. Hi,

    Mehrere Maschinen können zusammengehören, sagen wir A und C.
    Was ich jetzt haben möchte ist eine Liste aller Zeitpunkte von A und C, mit der jeweiligen Gesamtsumme.

    Also das hier
    00:00 - Gruppe AC - 5
    00:10 - Gruppe AC - 7
    00:12 - Gruppe B  - 3
    00:16 - Gruppe AC - 11 (nämlich die letzten 7 von A und die aktuellen 4 von C)
    00:27 - Gruppe AC - 16
    00:28 - Gruppe AC - 20 (die letzten 12 von A und die aktuellen von C)
    00:30 - Gruppe B  - 9

    Mit der Summierung hab ich ein Problem. Ich weiß nicht ob das per SQL geht und auch als Code hab ich bisher nur ziemlich wilde Konstrukte im Kopf. Wenns einfacher geht wär schön.
    Hat da jemand einen Ansatz?

    DB ist übrigens MySql, falls da mir da doch irgendwas brauchbares entgangen ist.

    du kannst auch nach mehreren Kriterien gruppieren, und ein Gruppierungskriterium kann auch ein Ausdruck sein.

    Z.B. könntest du nach IF(machine IN ('A', 'B'), 'AC', machine) gruppieren.

    SELECT mydate, IF(machine IN ('A', 'B'), 'AC', machine) AS machine_grp, SUM(mysum)  
    FROM mytbl  
    GROUP BY mydate, IF(machine IN ('A', 'B'), 'AC', machine)  
    
    ~~~.  
      
    Bis die Tage,  
    Matti
    
    -- 
    [Webapplikationen in C++ entwickeln](http://tntnet.org/)
    
    1. Z.B. könntest du nach IF(machine IN ('A', 'B'), 'AC', machine) gruppieren.

      Das ist halt nicht so flexibel. Es gibt ja nicht nur die beiden Gruppen sondern mehrere. Diese per Code hinzufügen wär nicht das Problem, aber dann mehrere verschachtelte if...

      Außerdem hab ich dann immer noch das Problem mit den verschiedenen Zeiten. Ich machs jetzt so dass ich das wirklich per Code zerpflücke. Das ist zwar mehr zu schreiben, aber es hat immerhin die Chance dass ich es auch in einem Monat noch verstehe.

      1. Hi,

        Z.B. könntest du nach IF(machine IN ('A', 'B'), 'AC', machine) gruppieren.
        Das ist halt nicht so flexibel. Es gibt ja nicht nur die beiden Gruppen sondern mehrere. Diese per Code hinzufügen wär nicht das Problem, aber dann mehrere verschachtelte if...

        hast du deine "Maschinengruppen" in der DB hinterlegt? Wenn du da einen eindeutigen Bezeichner pro Gruppe hast, gruppier doch danach.

        Außerdem hab ich dann immer noch das Problem mit den verschiedenen Zeiten. Ich machs jetzt so dass ich das wirklich per Code zerpflücke. Das ist zwar mehr zu schreiben, aber es hat immerhin die Chance dass ich es auch in einem Monat noch verstehe.

        Nach Zeiten zu gruppieren ist doch auch nicht so kritisch. Zeig doch mal etwas konkreteres, dann können wir dir auch konkret helfen.

        Bis die Tage,
        Matti

        1. Zeig doch mal etwas konkreteres, dann können wir dir auch konkret helfen.

          Siehe mein erster Post.

          Das Problem ist, die Abfragezeiten der einzelnen Maschinen sind nicht gleich, so dass ich pro Zeitpunkt nicht für alle Maschinen einer Gruppe einen Eintrag finde. Sonst könnte ich nach Zeit und Maschinengruppe gruppieren und dann die Stückzahlen aufsummieren.
          Dieses Summieren mache ich bisher im Code, für jeden gefundenen Eintrag zähle ich in der Maschinengruppe die Summe hoch.

          1. Hi,

            Das Problem ist, die Abfragezeiten der einzelnen Maschinen sind nicht gleich, so dass ich pro Zeitpunkt nicht für alle Maschinen einer Gruppe einen Eintrag finde. Sonst könnte ich nach Zeit und Maschinengruppe gruppieren und dann die Stückzahlen aufsummieren.
            Dieses Summieren mache ich bisher im Code, für jeden gefundenen Eintrag zähle ich in der Maschinengruppe die Summe hoch.

            Nach was willst du denn genau zeitlich gruppieren? Wenn es nicht genau nach dem Zeitstempel ist, dann doch wohl nach 5-Minuten-Intervallen? Dann gruppier doch nach der Tag+Stunde und dann noch nach FLOOR(minute/5). Kannst natürlich auch andere Intervalle wählen.

            Bis die Tage,
            Matti

          2. Hi, es kommt auch darauf an, welcher Maschine in einer Gruppe du die Priorität für die Zeit gibst, in deinem Beispiel scheint es A zu sein, verwendest du C hast du beim ersten C schon 2x A. Dein Problem ist ganz und gar nicht trivial und wie sonst sehr oft der Fall, kann man auch nicht sagen, es läge an einem suboptimalen Datenmodell.

            nummeriere vielleicht die Records für A, B und C sortiert nach Zeitstempel durch. Der erate A Record bekommt die 1, der zweite A Record die 2, der erste C Rrcord wieder die 1 usw. Wenn du dann die Gruppe AC zusammenfassen willst, dann fasst du die Einträge mit derselben Ordnungsnummer zusammen. In deinem Beispiel, würde das ein problem mit dem ersten C geben, was eigentlich zum 2. A gehören sollte. Also müsstest du für das 2. und jedes folgende Mitglied einer Gruppe  noch die zeitliche differenz einbeziehen: eine Instanz eines 2. oder folgenden Gruppenmitglieds gehört zu der Instanz des 1. Gruppenmitglieds wo die Differenz des Zeitstempels am geringsten ist plus diesbezüglich evt noch weitere Bedingungen eine Rolle spielen sollen. Aber es kommt wirklich darauf an, wer hinsicht des Zeitstempels die Priorität hat. Aus diesem Grund würde ich die weit weniger komplexe und ergebnissicherere Variante wählen: Bilde von 00:00 an Zeitfenster mit einer bestimmten Periodizität z.b. 3min (oder die geringste differenz aller Records), summiere in diese Zeitfenster hinein deine Gruppen und nimm am Ende nur die Zeitfenster wo win Wert drin ist (count != 0).

            Das sollte auch mit mysql zu machen sein.

            Eine andere Variante wäre noch, direkt beim Insert in die Tabelle eine Shadow Table zu pflegen, (prosa) wenn neuer eintrag für gruppeninstan (anhand vom Zeitstempel) aber gruppenmitglied nicht schon enthalten, füge hinzu ansonsten mach neue gruppeninstanz auf. Dies kann man nachträglich auch besser in PHP etc umsetzen als in SQL.

            Cheers, Frank

            1. Hallo

              Ich hab da über so manches nachgedacht.
              Bisher mach ich es so dass pro Gruppe eine Liste in PHP gefüllt wird. Pro Eintrag wird der Wert des Eintrags zum letzten Wert der Liste hinzugefügt. Daraus kann ich mir dann anschließend meine Zeitfenster selber schneidern.
              Ist zwar eher monströs, aber es funktioniert immerhin. Wobei ich schon gerne optimiere, möglichst so dass die Sache dabei höchstens im selben Maß komplizierter wird, wie der Code sich verkürzt :-)

              Hi, es kommt auch darauf an, welcher Maschine in einer Gruppe du die Priorität für die Zeit gibst, in deinem Beispiel scheint es A zu sein, verwendest du C hast du beim ersten C schon 2x A.

              Die Abfragezeitpunkte muss ich hinnehmen wie sie sind, an denen kann ich nichts drehen. Priorität hat dabei keine Maschine. Wenn die exakt gleiche Zeit drin steht, fallen ja beide Werte gleichzeitig in die Summe ein.