MySQL kumulierte Summe

Hallo in die Runde,

Ich brauche mal wieder eine Idee (und weiß leider momentan nicht, wie ich selber drauf komme bzw. wonach ich im Internet suchen müsste):

Ich habe eine Datenbank mit etwa 900.000 DS. Nun gibt es ein Feld, dass die Summe der Werte eines anderen Feldes aller in einer bestimmten Reihenfolge vorangehenden Datensätze enthält.

Beispiel
DS FeldWert FeldSum FeldSort (weitere Felder)
1 10 0 A1 (weitere Einträge)
2 23 33 A3
3 13 46 B1
4 22 68 B2
5 25 93 E45

Wenn jetzt neue Datensätze in die Tabelle eingefügt werden, sollen nach dem Einfügen die Werte in FeldSum neu berechnet und eingetragen werden.

Beispiel für einen neuen Datensatz:
DS FeldWert FeldSum FeldSort (weitere Felder)
1002 20 (neu) A4
würde also zwischen Datensatz 2 und 3 in der Reihenfolge eingeordnet werden (order by FeldSort).

Bis jetzt habe ich das mit einem PHP Script gelöst, dass in einer Abfrage die Werte in der gewünschten Reihenfolge liest und dann in einer Schleife die fortlaufende Summe bildet und jeden einzelnen Datensatz updatet. Das ist leider nicht sehr effektiv und dauert etwa 1,5-2 h pro Updatelauf (der allerdings mehrere neue oder geänderte Datensätze umfasst).

Hat jemand eine Idee, wie man das schneller / eleganter / effektiver lösen kann oder was die entscheidenden Suchbegriffe sind, um im Netz dazu was zu finden ?

Mal wieder Danke im Voraus für alle Ideen, Lo.

Hi lojope,
by einer Oracle-DB fiele deine Anfrage in den Bereich ‚analytic functions‘. Ob etwas Vergleihbares in MySQL exisiert, kann ich dir nicht sagen, frag mal bei Tante Gugl.

gruss
b.

Hallo,

eine MySQL-Funktion, die genau das gewünschte leistet ist mir nicht bekannt. Allerdings frage ich mich, warum es notwendig ist, die Summe in der Datenbank zu speichern, wo ich sie doch auf einfache Weise wärend der Ausgabe generieren kann. Im Normalfall würde ich nämlich sagen, die gehört nicht in die DB.

Bis jetzt habe ich das mit einem PHP Script gelöst, dass in
einer Abfrage die Werte in der gewünschten Reihenfolge liest
und dann in einer Schleife die fortlaufende Summe bildet und
jeden einzelnen Datensatz updatet. Das ist leider nicht sehr
effektiv und dauert etwa 1,5-2 h pro Updatelauf (der
allerdings mehrere neue oder geänderte Datensätze umfasst).

Das hört sich allerdings mühsam an.

Hat jemand eine Idee, wie man das schneller / eleganter /
effektiver lösen kann …

Ja.
Z.B. so etwa in dieser Art:
SELECT SUM (FeldWert) FROM tabelle ORDER BY FeldSort LIMIT $i

$i wäre dabei z.B. der Zähler in einer Schleife zur Ausgabe von FeldWert.

Klar was ich meine?

Dietmar

Hallo lojope,

eine laufende Summe ist in SQL mittels Unterabfrage formulierbar:

SELECT t.DS, t.FeldWert,
 ( SELECT SUM(u.FeldWert) FROM DeineTabelle u
 WHERE u.DS 

Wenn die laufende Summe in der Tabelle gespeichert werden soll, empfehle ich für die Berechnung im Rahmen des INSERTs einen Trigger zu verwenden.



    
    CREATE TRIGGER berechneFeldSum 
    BEFORE INSERT ON DeineTabelle
    FOR EACH ROW 
    BEGIN
     SET FeldSum = ( SELECT SUM(t.FeldWert) FROM DeineTabelle t
     WHERE t.DS 
    
    
    Peter

Hallo,

danke für die Anregungen. Ja verstanden :smile:
Das werde ich (wahrscheinlich) probieren.

Ich kann leider nicht alle Details offenlegen, aber es ist so, dass ich Datenbankdateien in einem proprietären Format habe (vermutlich „Altlast“ aus frühen EDV Tagen). Die Datensätze liegen in geordneter und sehr komprimierter Form mit Datensätzen variabler Länge vor. Sie werden über die Position in der Datei angesprochen.

Ich erzeuge nun eine MySQL Kopie der Daten. Jetzt brauche ich aber eine Verbindung um sie über die „alte“ Dateiposition ansprechen zu können. Jeder Datensatz besitzt also eine fiktive Länge, die nicht direkt aus der Länge der darin gespeicherten Daten errechnet werden kann (wegen der Komprimierung, die durchaus in jedem Datenfeld unterschiedlich sein kann). Weiterhin gibt es Updates zu den Daten, die im Prinzip aus Anweisungen wie „Lösche den Datensatz an Dateiposition x“ oder „Aktualisiere den Datensatz an Dateiposition y mit folgenden Werten“ bestehen. Die Position ändert sich bei jedem Update (durch Löschen oder Hinzufügen von Daten innerhalb der Datei). Auf das Format der Daten habe ich keinen Einfluss, ich kann sie nur analysieren und nachbilden, um die Prinzipien in MySQL und PHP nachzubauen.

Allerdings habe ich zwischenzeitlich eine andere Lösung als das „mühsame“ PHP Skript gefunden (das mühsame daran war die Wartezeit). Ich habe die gleiche Funktionalität als MySQL Stored Procedure nachgebaut und damit die Laufzeit von den genannten 2 Stunden auf etwa 10min reduziert. Damit kann ich leben.

Viele Grüße, Lo.

Hallo,

danke für die Beispiele.

Aber wenn ich das richtig verstehe, dann wird die Lösung mit dem Trigger bei jedem eingefügten Datensatz ausgeführt ? Wenn ich eine Abfrage ausführe, die z. B. 1000 Datensätze einfügt, wird die Funktion dann 1000mal ausgeführt ? Weiterhin habe ich im Rahmen des Updates eine Mischung von INSERTs, DELETEs und UPDATEs für die Datensätze.

Viele Grüße, Lo.

Ja, der Trigger wird bei jedem Datensatz ausgeführt, da MySQL, soweit ich weiß, nur Row-Level-Trigger unterstützt. Mit einem Statement-Trigger, der nur einmal ausgeführt wird, wäre es performanter.

Das liesse sich aber mittels Prozedur lösen, die nach dem Einfügen der 1000+ Datensätze ausgeführt wird und dann nur die Werte für die neuen Datensätze berechnet.

Peter