Arraywerte zusammenaddieren.

Alles, was PHP betrifft, kann hier besprochen werden.

Arraywerte zusammenaddieren.

Postby samurai » 12. May 2009 19:33

Hallo zusammen,

ich hole zunächst Werte aus mehreren Tabellen gleicher Struktur.
Diese Werte packe ich in ein mehrdimensionales array.
Das hat in etwa diese Form:

Code: Select all
$data[] = Array('Datum' => '12.11.2008', 'Kosten' => '12,78');
$data[] = Array('Datum' => '13.11.2008', 'Kosten' => '15,66');
$data[] = Array('Datum' => '12.11.2008', 'Kosten' => '22,28');
$data[] = Array('Datum' => '11.11.2008', 'Kosten' => '12,02');
$data[] = Array('Datum' => '12.11.2008', 'Kosten' => '16,38');
$data[] = Array('Datum' => '12.11.2008', 'Kosten' => '19,75');
$data[] = Array('Datum' => '13.11.2008', 'Kosten' => '10,13');
.....
.....


Es können ziemlich viele Datensätze werden.

Soweit so gut. Nun möchte ich nach Datum sortieren (z.B. aufsteigend) und pro Datum ein Summe der Kosten bilden.
So dass an diesem Beispiel am Ende rauskommt:

11.11.2008 = 12,02
12.11.2008 = 58,41
13.11.2008 = 25,79

Kann mir jemand einen guten Lösungsweg zeigen?

Danke vorab &
Beste Grüße
samurai
 
Posts: 45
Joined: 17. July 2006 13:39

Re: Arraywerte zusammenaddieren.

Postby Wiedmann » 12. May 2009 19:55

Warum lässt du dir das nicht gleich von MySQL so liefern?
(GROUP BY-Klauseln)
Wiedmann
AF Moderator
 
Posts: 17102
Joined: 01. February 2004 12:38
Location: Stuttgart / Germany

Re: Arraywerte zusammenaddieren.

Postby samurai » 12. May 2009 20:06

ich frage mehrere Tabellen (es können auch hunderte sein) ab. Diese haben allerdings die gleiche Struktur.
Ich könnte auch jedes Datum einzeln (z.B. 01.11.2008 dann 02.11.2008 dann 03.11.2008 usw.) in allen Tabellen abfragen, aber das würde viel Zeit kosten.
Deshalb habe ich gedacht, dass ich erst alle Tabellen in ein array packe und dann die Werte mit gleichem Datum addieren kann.

Aber ich weiß nicht wirklich wie ich das machen kann.

Oder kann man mit Group by eine SELECT Abfrage über meherer Tabellen machen und die Werte gleichzeitig addieren?
Wäre toll wenn ich ein irgendwo ein beispielhaftes script sehen könnte.
samurai
 
Posts: 45
Joined: 17. July 2006 13:39

Re: Arraywerte zusammenaddieren.

Postby Xardas der Dunkle » 12. May 2009 20:11

Sortieren kannst du mit usort:
Code: Select all
function multiSort($a, $b) {
      return $a['Kosten'] - $b['Kosten'];
}

usort($data, 'multiSort');
 


Gruppieren könntest du zwar array_reduce lösen, aber schöner währe es echt alles vorher bereits in SQL zu machen.
Code: Select all
function groupMulti($a, $b) {
      foreach($a as &$v) {
           if($v['Datum'] == $b['Datum']) {
                $v['Kosten'] += $b['Kosten'];
                return $v;
           }
      }
      $a[] = $b;
      return 
$a;
}

$data = array_reduce($data, 'groupMulti', Array());
 


Beides NICHT getestet.
User avatar
Xardas der Dunkle
 
Posts: 482
Joined: 09. March 2008 19:40
Location: /var/www

Re: Arraywerte zusammenaddieren.

Postby Wiedmann » 12. May 2009 20:16

Oder kann man mit Group by eine SELECT Abfrage über meherer Tabellen machen und die Werte gleichzeitig addieren?

Dazu ist eine Datenbank da. (Zuwas "tonnen" von Daten aus der DB holen und den Speicher von PHP/Apache belasten, wenn man doch nur ein simples Ergebnis braucht? Und das jedesmal wenn ein User im Browser auf einen Knopf drückt, um anders zu filtern oder zu sortieren)

Wäre toll wenn ich ein irgendwo ein beispielhaftes script sehen könnte.

Entspr. Beispiele zu GROUP BY findest du im MySQL Manual.

Aber vielleicht willst du dich überaupt erstmal mit MySQL, bzw. SQL, befassen.
Wiedmann
AF Moderator
 
Posts: 17102
Joined: 01. February 2004 12:38
Location: Stuttgart / Germany

Re: Arraywerte zusammenaddieren.

Postby samurai » 12. May 2009 20:22

schöner währe es echt alles vorher bereits in SQL zu machen.


ja gut aber wie kann ich das machen?


Sagen wir mal ich hab 5 Tabellen gleicher Struktur:

Tabelle 1
Datum / Kosten

Tabelle 2
Datum / Kosten

Tabelle 3
Datum / Kosten
.....
.....

jetzt will ich aus allen Tabellen die Summe der Kosen für jeweils ein Datum haben:

z.B.
1. Summe aller Kosten für 01.11.2008 aus allen Tabellen
2. Summe aller Kosten für 02.11.2008 aus allen Tabellen
3. Summe aller Kosten für 03.11.2008 aus allen Tabellen
4. usw. für den ganzen November...

?

Danke für eure Hilfe!
samurai
 
Posts: 45
Joined: 17. July 2006 13:39

Re: Arraywerte zusammenaddieren.

Postby Wiedmann » 12. May 2009 20:26

Indem du ganz normal deine Abfrage (egal ob jetzt eine oder mehrere Tabllen) machst, und darauf eine GROUP BY Aggregat-Funktion anwendest.
--> siehe das MySQL Manual. (dort gibt es einfache Beispiele zum Nachvollziehen und zum Verstehen wie es geht.)
Wiedmann
AF Moderator
 
Posts: 17102
Joined: 01. February 2004 12:38
Location: Stuttgart / Germany

Re: Arraywerte zusammenaddieren.

Postby Nobbie » 12. May 2009 21:24

samurai wrote:ich frage mehrere Tabellen (es können auch hunderte sein) ab. Diese haben allerdings die gleiche Struktur.


Mit anderen Worten: Dein Datenmodell ist total kaputt.

Das wäre doch jetzt die Gelegenheit, aus dem verkorksten Design eine vernünftige Anwendung zu machen.
Nobbie
 
Posts: 13182
Joined: 09. March 2008 13:04

Re: Arraywerte zusammenaddieren.

Postby samurai » 12. May 2009 22:23

Mit anderen Worten: Dein Datenmodell ist total kaputt.

Das wäre doch jetzt die Gelegenheit, aus dem verkorksten Design eine vernünftige Anwendung zu machen.


Nein nein, das passt schon.
Jeder Nutzer hat eine eigene Tabelle, in der auf dauer ganz viele Daten gespeichert werden.

Auf dauer gesehen macht es mehr Sinn die Daten in eigene Tabellen zu speichern, da so in 1-2 Jahren wahrscheinlich über 10 Mio. Datensätze in einer Tablle wären, was a) für Unübersicht sorgen würde und b) die Select-Abfrage deutlich verlangsamen würde wenn ich nur nach Daten eines einzigen Nutzers suche (was oft der Fall ist). Es wäre also total verkorkst es so zu machen, wie du es vorgeschlagen hast.

Trotzdem danke für deine Mühe.
samurai
 
Posts: 45
Joined: 17. July 2006 13:39

Re: Arraywerte zusammenaddieren.

Postby Xardas der Dunkle » 13. May 2009 14:43

samurai wrote:
Mit anderen Worten: Dein Datenmodell ist total kaputt.

Das wäre doch jetzt die Gelegenheit, aus dem verkorksten Design eine vernünftige Anwendung zu machen.


Nein nein, das passt schon.
Jeder Nutzer hat eine eigene Tabelle, in der auf dauer ganz viele Daten gespeichert werden.

Auf dauer gesehen macht es mehr Sinn die Daten in eigene Tabellen zu speichern, da so in 1-2 Jahren wahrscheinlich über 10 Mio. Datensätze in einer Tablle wären, was a) für Unübersicht sorgen würde und b) die Select-Abfrage deutlich verlangsamen würde wenn ich nur nach Daten eines einzigen Nutzers suche (was oft der Fall ist). Es wäre also total verkorkst es so zu machen, wie du es vorgeschlagen hast.

Trotzdem danke für deine Mühe.

Schwachsin, MySQL ist auf Geschwindigkeit ausgelegt. Es ist eher total verkorkst 1000 Tabellen mit der selben Struktur zu haben.
Und vor allem so einen Datenmüll mit PHP sortieren zu wollen. DAS ist langsam!
User avatar
Xardas der Dunkle
 
Posts: 482
Joined: 09. March 2008 19:40
Location: /var/www

Re: Arraywerte zusammenaddieren.

Postby grayFalcon » 13. May 2009 14:50

samurai wrote:Auf dauer gesehen macht es mehr Sinn die Daten in eigene Tabellen zu speichern, da so in 1-2 Jahren wahrscheinlich über 10 Mio. Datensätze in einer Tablle wären, was a) für Unübersicht sorgen würde


Was meinst du mit Unuebersicht?

samurai wrote: b) die Select-Abfrage deutlich verlangsamen würde wenn ich nur nach Daten eines einzigen Nutzers suche (was oft der Fall ist)


Schau dir mal CREATE INDEX im MySQL-Manual an. Wenn du einen Index ueber die Nutzer-ID erstellst, kannst du sehr schnell Daten anhand der Nutzer-ID aus der DB holen.

Das macht auf jeden Fall mehr Sinn, als fuer jeden Nutzer eine eigene Datentabelle zu haben.
grayFalcon
 
Posts: 7
Joined: 12. May 2009 09:08

Re: Arraywerte zusammenaddieren.

Postby Nobbie » 14. May 2009 12:48

samurai wrote:Auf dauer gesehen macht es mehr Sinn die Daten in eigene Tabellen zu speichern,


Nein, das macht nie einen Sinn. Dann braucht man auch kein SQL zu verwenden, da Dir sowieso kaum die mächtigen Funktionen einer relationalen Datenbank zur Verfügung stehen.

samurai wrote: da so in 1-2 Jahren wahrscheinlich über 10 Mio. Datensätze in einer Tablle wären, was a) für Unübersicht sorgen würde und b) die Select-Abfrage deutlich verlangsamen würde wenn ich nur nach Daten eines einzigen Nutzers suche (was oft der Fall ist)


Na und? Dafür ist MySQL doch gedacht. Die anderen beiden haben Dir ja schon entsprechend geantwortet und ich bin mir zudem völlig sicher, dass Du das "aus dem Bauch heraus" glaubst, statt getestet zu haben (da würdest Du Dich wundern, wie schnell MySQL ist, wenn man die entsprechenden Felder mit einem Index versieht.

samurai wrote: Es wäre also total verkorkst es so zu machen, wie du es vorgeschlagen hast.


Nein, total verkorkst ist es jetzt, aber es ließe sich ja zur Zeit noch relativ schnell umstellen. Je mehr Du Coding verschwendest, um das falsche Datendesign zu verwirklichen, umso weniger wirst Du bereit sein, es zu ändern. Und Du wirst auf Dauer nicht um eine Änderung herum kommen, denn genau Dein aktuelles Problem wird jämmerlich eingehen, wenn Du wirklich 10 Millionen Datensätze auf diese Weise gruppieren und addieren willst.

Hättest Du es richtig programmiert, würde ein einziges(!) SQL-Statement die Lösung bringen - und das ziemlich flott, auch bei Millionen von Datensätzen:

Code: Select all
SELECT `Datum`, Sum(`Kosten`) As Summe FROM `Tabelle` GROUP By `Datum` ORDER ASC By `Datum`


Fertig! Anschließend kannst Du die Treffermenge abklappern und ausgeben.

Wieviele Zeilen brauchst Du dafür - und vor allem, wieviel Rechenzeit brauchst Du dafür? Je mehr Tabellen und Datensätze Du abklappern mußt (Du mußt ja Dein Array erst einmal sukzessive füllen) und anschließend sortieren (holla die Waldfee bei 10 Millionen Sätzen) und dann die Teilsummen bilden - da wird das PHP Script stundenlang laufen, wenn es nicht durch irgendwelche Restriktionen bereits vorher abgebrochen wird.

Und ein Select auf einzelne Datensätze eines Kunden dauert trotz der 10 Millionen Datensätze nicht wesentlich länger, als wenn die Sätze auf 1000 Tabellen verteilt sind, dafür sorgt der INDEX der MySQL Engine.

Wenn Du das Datendesign (was das Wort nicht verdient) so läßt, wirst Du an allen Ecken und Enden immer wieder normale Datenbankfunktionen in PHP programmieren müssen, weil sie wegen des falschen Designs nicht in MySQL realisierbar sind. Und sei es nur die Anforderung, die Kunden alphabetisch zu sortieren, oder den Kunden mit dem höchsten Tagesumsatz zu finden, oder den Kunden, der den letzten Artikel vom Typ XYZ gekauft hat, oder oder oder - alles ganz normale Anforderungen, die mit Deinem Datenmodell nicht mit SQL-MItteln lösbar sind - und dabei ist es doch genau die Aufgabe von SQL, diese Dinge zu ermitteln.

Ich verstehe das auch nicht, zum einen fragst Du hier nach Hilfe, wie man etwas bestimmtes programmiert, aber wenn dann wirklich ein ernst gemeinter Hinweis kommt, der nicht nur die Lösung präsentiert sondern auch noch das Datenmodell in die richtige Richtung korrigiert - da interessiert es Dich nicht mehr und Du "machst besserwisserisch" auf cool - dabei fehlt Dir mit absoluter Sicherheit der notwendige Background, um das wirklich beurteilen zu können. Verlass Dich dich doch mal darauf, dass diese Ratschläge nicht einfach "aus dem Bauch" kommen sondern auf jahrelanger Erfahrung beruhen. Du wirst es nicht bereuen - aber wenn Du es läßt, wirst Du es bereuen, das ist ganz sicher, vor allem wenn es stimmt und in wenigen Jahren solche Datenmengen vorliegen. Dann bist Du ohne adäquate Unterstützung durch SQL aufgeschmissen - und da kann man dann gar nichts mehr machen, die Anwendung wird dann einfach durch die Datenmenge erdrückt.
Nobbie
 
Posts: 13182
Joined: 09. March 2008 13:04


Return to PHP

Who is online

Users browsing this forum: No registered users and 63 guests