Autor Beitrag
noidic
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 851

Win 2000 Win XP Vista
D7 Ent, SharpDevelop 2.2
BeitragVerfasst: Do 05.04.07 14:04 
Mahlzeit,

mal was zwischendurch, wenn mal wer Zeit hat.

Gegeben sei eine XML-Vorlage, die in etwa so aussieht:

ausblenden XML-Daten
1:
2:
3:
4:
5:
6:
7:
  ...
  <columns>
    <column fieldname="bla" function="average" />
    <column fieldname="blubb" function="sum" />
    ...
  </columns>
  ...


Außerdem haben wir ein ClientDataset, welches für jeden column-Knoten aus dem XML eine Spalte enthält und mit einigen hundert oder tausend Datensätzen befüllt ist.

Nun geht es darum, die angegebene Aggregatfunktion auf die Spalte anzuwenden. Mögliche Funktionen sind average, sum, min, max. Es ist ein Minimum von 0 für jede Spalte vorauszusetzen.

Die erste Idee war, einfach eine 2. Abfrage zu bauen und den Datenbankserver die Aggregate berechnen zu lassen, das geht aber nicht, da nach der Abfrage, aber vor der Berechnung noch Datensätze konsolidiert werden.

Nun kommt meine zweite und aktuelle Idee zum tragen, die da wäre das Dataset für jede Spalte, die eine Aggregatfunktion hat, einmal komplett durchzulaufen und zu berechnen. Die Berechnungen sähen wie folgt aus:

max (min entsprechend andersrum):

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function GetMax(ADataset : TClientDataSet; AFieldName : String) : double;
begin
  Result := 0;
  ADataset.first;
  while not ADataset.eof do
  begin
    if ADataSet.FieldByName(AFieldName).asFloat > Result then
      Result := ADataSet.FieldByName(AFieldName).asFloat;
    ADataset.next;
  end;
end;


sum:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
function GetSum(ADataset : TClientDataSet; AFieldName : String) : double;
begin
  Result := 0;
  ADataset.first;
  while not ADataset.eof do
  begin
    Result := Result + ADataSet.FieldByName(AFieldName).asFloat;
    ADataset.next;
  end;
end;


average:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
function GetAvg(ADataset : TClientDataSet; AFieldName : String) : double;
var
  cnt : Integer;
  sum : float;
begin
  Result := 0;
  cnt := 0;
  sum := 0;
  ADataset.first;
  while not ADataset.eof do
  begin
    if not ADataSet.FieldByName(AFieldName).isNull then
    begin
      inc(cnt);
      sum := sum + ADataSet.FieldByName(AFieldName).asFloat;
    end;
    ADataset.next;
  end;
  Result := sum / cnt;
end;


Auch wenns noch nicht umgesetzt ist, so weiss ich doch, dass es nicht besonders schnell sein wird.

Nun die Preisfrage :)

Hat wer eine Idee, die Berechnung schneller durchzuführen?

Viel Spass :)

_________________
Bravery calls my name in the sound of the wind in the night...
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Do 05.04.07 21:22 
Gehört zwar irgendwie mehr in den Bereich Datenbanken, aber hier mal'n kleiner Tipp:

Delphi besitzt bei den DB-omponenten die Möglichkeit das Result-Set zwischenzuspeichern (z.B. Temporär-Tabellen). Auf diese kannst Du problemlos deine Aggregat-Funktionen anwenden.

Ansonsten: Berechne einfach alle Aggregat-Funktionen als zusätzliche Spalten und werte nur die aus, die ausgewertet werden sollen ;-) (@DBler: Schlagt mich dafür jetzt nicht --- es funzt, auch wenn's Performance auf dem DBMS zieht wie Seuche!!!).

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
noidic Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 851

Win 2000 Win XP Vista
D7 Ent, SharpDevelop 2.2
BeitragVerfasst: Di 10.04.07 08:19 
Die erste Idee wäre mal zu testen.

Die zweite verstehe ich so, dass ich schon bei der Abfrage der Daten die Aggregate berechnen soll. Das geht nicht, da zu dem Zeitpunkt noch Zeilen im Ergebnis enthalten sind, die beim tatsächlichen Ergebnis nicht mehr enthalten sind und somit das Aggregat verfälschen würden.

_________________
Bravery calls my name in the sound of the wind in the night...