Einzelnen Beitrag anzeigen

apm

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

unbestimmte Anzahl TFDQuerys abgleichen

  Alt 19. Feb 2021, 14: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