über die Feiertage habe ich mir mal wieder Gedanken gemacht, wie ich die Auswertung einer Kundendatenbank in meinem Programm entscheidend beschleunigen kann. Vlt. helfen mir ein paar Hinweise/Ideen von Euch.
Kurz zur Installation:
- Keine Multiuserfähigkeit (ist für die Anwendung nicht nötig). Alle DBFs werden exclusiv geöffnet.
- Kundendatenbank in EINER DBF mit 131 Feldern und bis zu 200.000 Datensätzen
- Läuft i.d.R. lokal, kann aber auch auf einem Netzlaufwerk installiert sein
- Native Xbase-Code
Es müssen keine einzelnen Datensätze gefunden werden, sondern es wird immer die gleiche Ergebnistabelle erstellt in der ca. 60 numerische Felder der Kundendatei nach unterschiedlichen Kriterien summiert aufgelistet werden. Auf einer Dialogseite können über Eingabefelder (SLEs), Listboxen, Checkboxes und Radiobuttons ganz unterschiedliche Kriterien für die Filterung der DBF gewählt werden. Nach Klick auf "Auswertung" wird über die Abfrage der Kriterien-Elemente eine (teilweise SEHR) komplexe Filterbedingung zusammengestellt.
(1) Zunächst hatte ich dann mit "SET FILTER TO &MeinFilter" und "Go Top" die Filterbedingung aktiviert und den ersten Datensatz angesprungen. Ich weiß dann allerdings (zunächst) nicht, wie viele passende Datensätze vorhanden sind und kann z.B. keine passende Progressbar anzeigen. Außerdem dauert die Suche bis zum ersten Treffer u.U. ziemlich lange. Ein anschließendes "RECCOUNT()" dauert wieder ewig.
(2) Seit einiger Zeit habe ich das dergestalt geändert, dass ich immer in einer Do-While-Schleife die gesammte DBF durchlaufe und über "IF &MeinFilter" prüfe, ob der aktuelle Satz passt oder nicht. Anzeigeproblem gelöst, aber eben auch nicht gerade schnell.
Egal ob (1) oder (2), es werden dann immer die Werte gesammelt und in Variablen aufaddiert. Also so ähnlich wie bei "Total on..."
Ich versuche, es noch etwas deutlicher zu beschreiben:
Der Anwender kann aus einer Listbox auswählen, ob nur eine, mehrere oder alle Filialen einbezogen werden sollen.
Der Anwender kann aus einer Listbox auswählen, ob nur ein Kundenberater oder mehrere oder alle Berater einbezogen werden sollen.
Der Anwender kann über einer Checkbox wählen, ob nur Mitglieder ausgewertet werden sollen.
Der Anwender kann über einen Radiobutton wählen, ob nur Kunden einer bestimmten Risikogruppe ausgwertet werden.
Der Anwender kann über SLEs einstellen, dass Kunden mit bestimmten Beträgen im Topf1, Topf2.... zusammengefasst werden.
.... (es gibt noch einige "Filterschaltungen" mehr).
Alle Bedingungen sind UND-Bedingungen. Die Anzahl der auszuwertenden Datensätze wird also immer kleiner.
Scope fällt aus, weil egal wie ich den Index setze, (fast) nie die relevanten Datensätze logisch hintereinander liegen würden.
&MeinFilter sieht z.B. so aus: "EPENG->Filiale $ {'Düsseldorf', 'Köln', 'München', 'Bedburg', 'Glesch'};
.AND. EPENG->Berater $ {'KDB01','KDB02','FKB03','FKB07','SER01','SER02','SER03'};
.AND. EPENG->Mitglied = 'J';
.AND. EPENG->ART = 'P';
(Das ist ein eher kleiner, einfacher Filtertext.)
Momentan läuft es also ungefähr so:
Code: Alles auswählen
---
dbSelect("EPENG")
dbGoTop()
Do while !eof()
if &MeinFilter
if EPENG->aktivv >= Topf1AktivVon .AND. EPENG->aktivv < Topf1AktivBIS
nAktivvolumen1+=EPENG->aktivv
nAnlagevolumen1+=EPENG->anlagev
nErgebnis1+=EPENG->Ergebnis
elseif EPENG->aktivv >= Topf2AktivVon .AND. EPENG->aktivv < Topf2AktivBIS
nAktivvolumen1+=EPENG->aktivv
nAnlagevolumen1+=EPENG->anlagev
nErgebnis1+=EPENG->Ergebnis
elseif EPENG->aktivv >= Topf2AktivVon .AND. EPENG->aktivv < Topf2AktivBIS
nAktivvolumen2+=EPENG->aktivv
nAnlagevolumen2+=EPENG->anlagev
nErgebnis2+=EPENG->Ergebnis
elseif EPENG->aktivv >= Topf3AktivVon .AND. EPENG->aktivv < Topf3AktivBIS
nAktivvolumen3+=EPENG->aktivv
nAnlagevolumen3+=EPENG->anlagev
nErgebnis3+=EPENG->Ergebnis
endif
dbSkip()
Enddo
...
Meine Fragen/Gedanken kreisen um folgende Möglichkeiten/Alternativen:
o Könnte es etwas bringen, die ganze DBF in ein Array zu ziehen und dann quasi im Speicher zu arbeiten und nicht auf der DBF?
o Wie wäre es, wenn ich tatsächlich den Filter aufbaue, setze, dann die Ergebnisdatensätze in eine TEMP exportiere und nur diese auswerte?
o Sollte ich statt "IF &MeinFilter..." die einzelnen Filterteile in einer Art "Filterkaskade" mit tief verschachtelten IF-THEN-ELSEIF-Strukturen abfragen? Wird irre unübersichtlich, oder?
o Bei jedem Treffer werden ca. 60 Summenvariablen bearbeitet. Wären 60 Durchläufe mit jeweils EINER bearbeiteten Summenvariablen schneller? Ich denke eher nicht, oder?
o ... ?
Wer hat ein paar zielführende Tipps für mich, die ich mal ausprobieren kann?
Wie geht Ihr bei solchen Aufgabenstellungen vor?
Wer sich ein Bild davon machen will, kann hier nachsehen: https://www.ggbbg.de/content/dam/f8998- ... er2013.pdf
Seiten 10-14 sind gemeint.
Vielen Dank an alle, die hier mal mit denken oder mitdenken.
Viele Grüße, besonders an Jan , aber natürlich auch an alle anderen
Christof
p.s. "Frohes, neues Jahr!" (Darf man noch sagen, oder?)