AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

unbestimmte Anzahl TFDQuerys abgleichen

Ein Thema von apm · begonnen am 19. Feb 2021 · letzter Beitrag vom 19. Feb 2021
Antwort Antwort
apm

Registriert seit: 22. Nov 2010
28 Beiträge
 
#1

unbestimmte Anzahl TFDQuerys abgleichen

  Alt 19. Feb 2021, 15:29
Moin!
Ich habe eine Frage zur potentiellen Performance und Erfahrungen eurerseits.

Situation:
Ich habe eine unbestimmte Anzahl von Querys, welche jeweils eine ID-Spalte halten. Die Daten sind vorsortiert. Über alle Querys muss ich die ID-Übereinstimmungen finden.
Mit Dem Ergebnis will ich eine SQL-Abfrage füttern.
Ich könnte einfach alle IDs aus einer Querys nehmen und jeweils einen Abgleich des gewünschten Feldes für diese durchführen. Das könnte aber zu sehr langen SQL-Strings führen. Entsprechend will ich dort eine Vorverarbeitung durchführen.

Eine Überführung der IDs in int-Arrays erscheint mir von den Arbeitsschritten her eigentlich unnötig.
Ich mache jetzt das:
- Querys auf Beschaffenheit kontrollieren und nur die weiter betrachten, die wichtig sind
- Wenn nur eine Query übrig bleibt kann ich die IDs dieser einfach verarbeiten
- Wenn mehrere Querys übrig bleiben suche ich mir die längste, um eine übergreifende Schleife zu starten
-- Ich kontrolliere die aktuellen Daten über alle Query auf Gleichheit
--- bei Erfolg habe ich eine ID gefunden
--- bei Fehlschlag schaue ich mir die IDs aller Querys an und schreite voran, solang die IDs der zu überprüfenden Querys kleiner sind als die der Schleifen-Query
--- am Ende schreite ich einen Datensatz in der Schleifen-Query weiter und die Checks beginnen erneut

Die Tests schauen soweit gut aus. Geht das ganze aber effektiver / schneller?


Delphi-Quellcode:
function func_findPoiIds(sArrIdField : TArray<String>; quArrData : TArray<TFDQuery>) : String;
  var sIdFieldLong : String;
      quDataLong : TFDQuery;
      bQuAction : Boolean;
      i, iPos : Integer;
begin
  Result := '0';
  if Length(sArrIdField) <> Length(quArrData) then Exit;

  //Start Entfernen leerer Elemente
    i := 0;
    while i < Length(quArrData) do
    begin
      if quArrData[i].IsEmpty then
      begin
        Delete(quArrData, i, 1);
        Delete(sArrIdField, i, 1);
        Dec(i);
      end;

      Inc(i);
    end;

    if Length(sArrIdField) <> Length(quArrData) then Exit;
  //Ende Entfernen leerer Elemente


  //Start nur ein Element übrig
    if Length(quArrData) = 1 then
    begin
      quArrData[0].First;

      while not quArrData[0].Eof do
      begin
        Result := Result + ',' + quArrData[0].FieldByName(sArrIdField[0]).AsString;
        quArrData[0].Next;
      end;

      Exit;
    end;
  //Ende nur ein Element übrig


  //Start Längstes Element finden
    iPos := 0;
    for i := 1 to Length(quArrData)-1 do
      if quArrData[i].RecordCount > quArrData[iPos].RecordCount then
        iPos := i;

    sIdFieldLong := sArrIdField[iPos];
    Delete(sArrIdField, iPos, 1);

    quDataLong := quArrData[iPos];
    quDataLong.First;
    Delete(quArrData, iPos, 1);

    for i := 0 to Length(quArrData)-1 do
      quArrData[i].First;
  //Ende Längstes Element finden


  //Start QueryVergleich
    while not quDataLong.Eof do
    begin
        //Start ID anfügen und weiter springen
          bQuAction := true;

          for i := 0 to Length(quArrData)-1 do
            if quDataLong.FieldByName(sIdFieldLong).AsInteger <> quArrData[i].FieldByName(sArrIdField[i]).AsInteger then
            begin
              bQuAction := false;
              Break;
            end;

          if bQuAction then
          begin
            Result := Result + ',' + quDataLong.FieldByName(sIdFieldLong).AsString;

            quDataLong.Next;
            for i := 0 to Length(quArrData)-1 do
              quArrData[i].Next;

            Continue;
          end;
        //Ende ID anfügen und weiter springen


        //Start QuerryData hochsetzen
          for i := 0 to Length(quArrData)-1 do
          begin
            bQuAction := false;

            while not quArrData[i].Eof
            and (quDataLong.FieldByName(sIdFieldLong).AsInteger > quArrData[i].FieldByName(sArrIdField[i]).AsInteger) do
            begin
              quArrData[i].Next;
              bQuAction := true;
            end;

            if bQuAction then Break;
          end;

          //nach PositionsVeränderung neue Prüfung einleiten
          if bQuAction then Continue;
        //Ende QuerryData hochsetzen

      quDataLong.Next;
    end;
  //Ende QueryVergleich
end;
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.065 Beiträge
 
Delphi 12 Athens
 
#2

AW: unbestimmte Anzahl TFDQuerys abgleichen

  Alt 19. Feb 2021, 16:37
Hängen da auch noch paar Edits/Grids an diesen DataSets?
Dann ist es natürlich langsam, wenn man währenddessen nicht mit DisableControls arbeitet.

Und warum àlles manuell durchscrollen und die ID suchen, anstatt Locate zu benutzen?


Vom Tempo her ist es fast egal, auch wenn rückwärts natürlich dennoch schneller ist, weil insgesamt im Array weniger einträge verschoben werden müssen.
Und zusätzlich ist der Code auch noch wesentlich kürzer/übersichtlicher.
Zitat:
Delphi-Quellcode:
    i := 0;
    while i < Length(quArrData) do
    begin
      if quArrData[i].IsEmpty then
      begin
        Delete(quArrData, i, 1);
        Delete(sArrIdField, i, 1);
        Dec(i);
      end;

      Inc(i);
    end;
Delphi-Quellcode:
    for i := High(quArrData) downto 0 do
      if quArrData[i].IsEmpty then
      begin
        Delete(quArrData, i, 1);
        Delete(sArrIdField, i, 1);
      end;
Zitat:
Delphi-Quellcode:
            bQuAction := false;

            while not quArrData[i].Eof
            and (quDataLong.FieldByName(sIdFieldLong).AsInteger > quArrData[i].FieldByName(sArrIdField[i]).AsInteger) do
            begin
              quArrData[i].Next;
              bQuAction := true;
            end;

            if bQuAction then Break;
Delphi-Quellcode:
            //bQuAction := quArrData[i].Locate(sArrIdField[i], quDataLong.FieldByName(sIdFieldLong).AsInteger);
            bQuAction := quArrData[i].LocateEx(sArrIdField[i], quDataLong.FieldByName(sIdFieldLong).AsInteger, [lxNext]);
            if bQuAction then Break;
[edit]
Ich seh grad, es war hier kein <> sondern >
und Locate arbeitet natürlich wie =, also das Gegenteil von <>
Hatte hier zuerst die Schleife von //Start ID anfügen und weiter springen , welche aber über das Array und kein Dataset läuft.
Bei einem sortierten Array kann man könnte man aber ebenfalls ein TArray.BinarySearch verwenden.
[/edit]

PS: Was soll das Zweite if Length(sArrIdField) <> Length(quArrData) then Exit; machen?
Wenn es beim Ersten schon gleich war und dazwischen links und rechts genau gleichviel gelöscht wurde, dann kann es dort NIEMALS unterschiedlich sein.


Ansonsten isses ein bissl schwer direkt zu erkennen, was nun genau gemacht wird, aber mit bissl kürzerem/übersichtlicherm Code versteht man es womöglich auch schneller.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (19. Feb 2021 um 17:03 Uhr)
  Mit Zitat antworten Zitat
apm

Registriert seit: 22. Nov 2010
28 Beiträge
 
#3

AW: unbestimmte Anzahl TFDQuerys abgleichen

  Alt 19. Feb 2021, 16:48
Hängen da auch noch paar Edits/Grids an diesen DataSets?
An den Querys sind keine visuellen Sachen angeschlossen.

Und warum àlles manuell durchscrollen und die ID suchen, anstatt Locate zu benutzen?
Locate schaue ich mir mal an.

Vom Tempo her ist es fast egal, auch wenn rückwärts natürlich dennoch schneller ist, weil insgesamt im Array weniger einträge verschoben werden müssen.
Und zusätzlich ist der Code auch noch wesentlich kürzer/übersichtlicher.
Das ist die Gewohnheit gewesen. Normalerweise schreibe ich eher up als down. Aber das ist schon richtig.


PS: Was soll das Zweite
Zitat:
if Length(sArrIdField) <> Length(quArrData) then Exit;
machen?
Das ist ein Fehler ... Das muss ein Check auf ein leeres Bearbeitungsarray sein. Gut gesehen!


Würde es an sich noch einen anderen Ansatz geben, der besser ist als meiner? (Außer die schon gefundenen Sachen natürlich. )
  Mit Zitat antworten Zitat
Antwort Antwort


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 20:35 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