AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi OnCalcFields... gibt es einen effizienteren Weg?
Thema durchsuchen
Ansicht
Themen-Optionen

OnCalcFields... gibt es einen effizienteren Weg?

Ein Thema von zack0r · begonnen am 5. Apr 2009 · letzter Beitrag vom 6. Apr 2009
Antwort Antwort
Seite 1 von 2  1 2      
zack0r

Registriert seit: 5. Jan 2005
Ort: Rosenheim
25 Beiträge
 
#1

OnCalcFields... gibt es einen effizienteren Weg?

  Alt 5. Apr 2009, 20:22
Datenbank: DBISAM • Version: 4 • Zugriff über: Direkt
Hallo,
ich bin an einer Software dran und habe ein Performance Problem. Lokal kann man arbeiten aber übers Netzwerk wird es schnell sehr träge. Hier ein Auszug aus dem Datenmodell:

Zitat:
Artikel
----
lfdnr (Primary Key)
bezeichnung
nachweise
behandlungszustand

Nachweise
----
idx (Primary Key)
nachweis

ArtikelNachweise
----
idx (Primary Key)
lfdnr (->Fremdschlüssel auf Artikel->lfdnr)
nachweisnr (->Fremdschlüssel auf Nachweise->idx)
Für das Feld Behandlungszustand gibt es auch entsprechende Tabellen. In der Tabelle Artikel sind noch etwa 20 weitere Felder.

In meinem Hauptfenster ist ein Grid das mit einem Query verbunden ist (qartikel). Hier der SQL-Code:
SQL-Code:
SELECT *
FROM artikel AS A LEFT OUTER JOIN bestellungenpos AS B ON A.lfdnr = B.artikel
ORDER BY lfdnr DESC
So, jetzt will in in diesem Grid die Datensätze aus Nachweise und Behandlungszustand anzeigen. Aber da es ja 1:N-Beziehung ist kann ich kein lookup-Feld einsetzen. Was ich will ist quasi eine mit Komma getrennte Anzeige der entsprechenden Datensätze. Dafür habe ich mich der OnCalcFields-Methode bedient. Dies funktioniert auch, aber ist leider recht langsam.
Jetzt meine Frage, fällt jemandem ein Weg ein wie man das Effizienter und Performanter implementieren kann?

Delphi-Quellcode:
procedure Tfmain.qartikelCalcFields(DataSet: TDataSet);
var
  i: integer;
  tmpstr: string;
begin
  tmpstr := '';
  if (DataSet.FieldByName('lfdnr').value <> NULL) and (DataSet.FieldByName('lfdnr').Asinteger <> 0) then
  begin
    qartikelbz.open;
    qartikelbz.Filter := '(lfdnr = ' + DataSet.FieldByName('lfdnr').AsString + ')';
    qartikelbz.filtered := true;
    for i := 0 to qartikelbz.filterrecordcount - 1 do begin
      tmpstr := tmpstr + '+' + qartikelbz.FieldByName('bztext').AsString;
      qartikelbz.next;
    end;
    DataSet.FieldByName('behandlungszustand').AsString := tmpstr;

    tmpstr := '';
    qartikelnw.open;
    qartikelnw.Filter := '(lfdnr = ' + DataSet.FieldByName('lfdnr').AsString + ')';
    qartikelnw.filtered := true;
    for i := 0 to qartikelnw.filterrecordcount - 1 do begin
      tmpstr := tmpstr + qartikelnw.FieldByName('nachweisetext').AsString + ', ';
      qartikelnw.next;
    end;
    i := length(tmpstr);
    if (tmpstr <> '') and (tmpstr[i-1] = ',') then setlength(tmpstr,i - 2);
    DataSet.FieldByName('nachweise').AsString := tmpstr;
  end;
end;
Zum Anschluss noch eine auswertung die DBIsam mir ausspuckt wenn ich das Query Ausführe:
Zitat:
================================================== ==============================
SQL statement (Executed with 4.26 Build 3)
================================================== ==============================

SELECT *
FROM artikel AS A LEFT OUTER JOIN bestellungenpos AS B ON A.lfdnr = B.artikel
ORDER BY lfdnr DESC

Tables Involved
---------------

artikel (A) table opened shared, has 1094 rows
bestellungenpos (B) table opened shared, has 251 rows

Result Set Generation
---------------------

Result set will be canned

Result set will consist of one or more rows

Result set will be ordered by the following column(s) using a case-sensitive
temporary index:

lfdnr DESC

Join Ordering
-------------

The driver table is the artikel table (A)

The artikel table (A) is joined to the bestellungenpos table (B) with the LEFT
OUTER JOIN expression:

A.lfdnr = B.artikel

Optimizer will attempt to re-order the joins to a more optimal order
Use the NOJOINOPTIMIZE clause at the end of the SQL statement to force the
optimizer to leave the joins in their declared order

The joins are already in optimal order and cannot be optimized any further

Join Execution
--------------

Costs ARE NOT being taken into account when executing this join
Use the JOINOPTIMIZECOSTS clause at the end of the SQL statement to force the
optimizer to consider costs when optimizing this join

The expression:

A.lfdnr = B.artikel

is OPTIMIZED

================================================== ==============================
>>>>> 1112 rows affected in 0,031 seconds
================================================== ==============================
Ich hoffe jemandem fällt was ein, ich bin echt ratlos. Vielen Dank schonmal

Gruß florian
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: OnCalcFields... gibt es einen effizienteren Weg?

  Alt 5. Apr 2009, 20:25
Die Berechnung direkt in der Abfrage durchführen
Markus Kinzler
  Mit Zitat antworten Zitat
zack0r

Registriert seit: 5. Jan 2005
Ort: Rosenheim
25 Beiträge
 
#3

Re: OnCalcFields... gibt es einen effizienteren Weg?

  Alt 5. Apr 2009, 20:30
Versteh nich was du meinst. Kannst du vielleicht etwas präziser werden?
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: OnCalcFields... gibt es einen effizienteren Weg?

  Alt 5. Apr 2009, 20:38
Ich meinte die temporären Felder direkt in der Abfrage berechnen zu lassen. in deinem fall würde ich aber eigen Abfragen verwenden
Markus Kinzler
  Mit Zitat antworten Zitat
zack0r

Registriert seit: 5. Jan 2005
Ort: Rosenheim
25 Beiträge
 
#5

Re: OnCalcFields... gibt es einen effizienteren Weg?

  Alt 5. Apr 2009, 21:42
hmm du meinst SubQuerys oder was? Aber ich kann doch mit SQL keinen String aus den Elementen bauen, oder doch?
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#6

Re: OnCalcFields... gibt es einen effizienteren Weg?

  Alt 5. Apr 2009, 21:46
Nein als eigene Abfrage. Die Berechnung wird sonst für jede Zeile durchgeführt. Bei 1000 zeilen würde diese dann 1000 mal erfolgen ( wobei er jedes Mal über alle 100 Zeilen gehen würde)
Deshalb eine Abfrage die die Anzahlen der mittlet ( einmalig)
Markus Kinzler
  Mit Zitat antworten Zitat
zack0r

Registriert seit: 5. Jan 2005
Ort: Rosenheim
25 Beiträge
 
#7

Re: OnCalcFields... gibt es einen effizienteren Weg?

  Alt 5. Apr 2009, 22:02
hmm ok macht sinn...aber dann kann ich keine Berechneten Felder mehr benutzen oder? Weil die kann ich ja nur in dem OnCalcFields bearbeiten und sonst nicht.
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#8

Re: OnCalcFields... gibt es einen effizienteren Weg?

  Alt 5. Apr 2009, 22:08
Brauchst du aber auch nicht, weil du auch in einer Abfrage virtuelle Felder erzeugen kannst
Markus Kinzler
  Mit Zitat antworten Zitat
zack0r

Registriert seit: 5. Jan 2005
Ort: Rosenheim
25 Beiträge
 
#9

Re: OnCalcFields... gibt es einen effizienteren Weg?

  Alt 5. Apr 2009, 22:21
hmm also ich habs jetz so gemacht: Hab ein neues Query gemacht in dem ich die Felder berechne. Im OnCalcFields von meinem qartikel Query hab ich jetz nur noch diesen code:
Delphi-Quellcode:
  qbznw.Locate('lfdnr', DataSet.FieldByName('lfdnr').AsString, []);
  DataSet.FieldByName('behandlungszustand').AsString := qbznw.FieldByName('behandlungszustaende').AsString;
  DataSet.FieldByName('nachweise').AsString := qbznw.FieldByName('nachweise').AsString;
War das das was du meintest?

Leider ist es aber damit immernoch nicht schneller

#EDIT

Also das da oben kann ich mir ja sparen, da ich die Felder ja jetz als Lookup-Felder definieren kann. Das Funktioniert auch. Aber lahm isses immernoch.


GN8 zack0r
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#10

Re: OnCalcFields... gibt es einen effizienteren Weg?

  Alt 6. Apr 2009, 05:36
Du brauchst keine CalcFelder mehr. Im ersten Schritt Anzahl berechnen, dann die eigentlichen Werte
Markus Kinzler
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:05 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz