Nach 2 Attributen Filtern

Zugriff, Engines, Konvertierung. Von ADS über DBF bis zu SQL.

Moderator: Moderatoren

Antworten
monokeros
Rookie
Rookie
Beiträge: 7
Registriert: Fr, 12. Nov 2021 15:34
Hat sich bedankt: 3 Mal

Nach 2 Attributen Filtern

Beitrag von monokeros »

Hallo Zusammen,
ich hänge nun seit längerem an einem eigentlich simplen Problem. Ich übersehe etwas, ich weiß aber nicht was...
Ich möchte einfach eine Tabelle nach 2 Attributen Filtern (nach einander).
Zum Beispiel zu erst den Autohersteller nach "GM" Filtern und dann alle Modelle mit 3 Türen.
Um alle 3-Türigen GM Modelle zu finden.

Ich habs mit 2 Scopes versucht (funktioniert aber nicht da der alte Scope beim neugesetzem Index nicht mehr gesetzt ist):

Code: Alles auswählen

SetIndex("Hersteller")
DbSetScope(SCOPE_BOTH, "GM")
SetIndex("Tueren")
DbSetScope(SCOPE_BOTH, 3)
Ich habs mit kombiniertem Index versucht (klappt aber auch nicht wie ich dachte).
Auszug der Indexierung:

Code: Alles auswählen

INDEX ON ltrim(rtrim(Str(HERSTELLER))) + "-" + ltrim(rtrim(Str(Tueren))) TAG "HerstellerTueren" TO ind_autos
In der Funktion:

Code: Alles auswählen

scope := ltrim(rtrim(Str("GM"))) + "-" + ltrim(rtrim(Str(3)))
DbSetScope(SCOPE_BOTH, scope)
1 Scope 1 Filter klappte ebenfalls nicht, da bin ich mir aber beim Filter unsicher (den baute ich anhand des Beispiels der Doku auf):

Code: Alles auswählen

SetIndex("Hersteller")
DbSetScope(SCOPE_BOTTOM, "GM")
DbSetFilter( {|| ftrim ( "Tueren" ) $ ftrim(Str(3))})
DbGoTop()
Ich würde mich freuen wenn mir jemand, bei dem recht simplen Problem, helfen könnte.
Zuletzt geändert von monokeros am Mi, 01. Dez 2021 10:22, insgesamt 1-mal geändert.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Nach 2 Attributen Filtern

Beitrag von Tom »

Erst der Scope und dann der Filter ist schon richtig. Du kannst natürlich ganz simpel dahergehen und einfach einen Filter auf beides setzen:

Code: Alles auswählen

DbSetFilter({||Hersteller == "GM" .AND. Tueren == 3})
DbGotop()
DO WHILE !Eof()
  * Datensätze
  DbSkip(1)
ENDDO
Wenn es aber viele Einträge gibt, wären Scope und Filter in Kombination ideal:

Code: Alles auswählen

DbSetIndex("Hersteller") // falls der Index wirklich so heißt
DbSetScope(SCOPE_BOTH,"GM")
DbSetFilter({||Tueren == 3})
DbGotop() // und dann wie oben
Herzlich,
Tom
monokeros
Rookie
Rookie
Beiträge: 7
Registriert: Fr, 12. Nov 2021 15:34
Hat sich bedankt: 3 Mal

Re: Nach 2 Attributen Filtern

Beitrag von monokeros »

Vielen Dank Tom! Super simpel eigentlich...
Habe das ganze jetzt mit Scope und Filter gelöst, da die Funktion auch ohne die zweite Bedingung aufgerufen wird und der Scope entsprechend immer gebraucht wird.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Nach 2 Attributen Filtern

Beitrag von Tom »

Freut mich! :)

Ja, ist eigentlich ganz simpel. Man kann sich auch über die Kommandos annähern, da ist die Syntax noch etwas übersichtlicher (SET FILTER/SET SCOPE). Wenn man große Datenmengen hat und nach kleinen Teilmengen sucht, ist die Scope/Filter-Kombination sehr hilfreich.
Herzlich,
Tom
flanelli
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 151
Registriert: Di, 11. Mai 2010 16:27
Hat sich bedankt: 3 Mal
Danksagung erhalten: 9 Mal

Re: Nach 2 Attributen Filtern

Beitrag von flanelli »

und das besonders feine am scope ist der umstand, dass man z.b. in einer ansicht der eingegrenzten
datenmenge einen weiteren datensatz ( der den eingrenzungsbedingungen entspricht ) hinzufügen möchte,
dies ebenso sehr schnell geschieht und vorhandene indexe ebenfalls aktualisiert werden.
ist dann ein nachgesetzter filter kein "eingrenzungsmonster" klappt eine schnelle weiterbearbeitung,
ergänzung, löschung in der datenmenge ohne nennenswerten performanceverlust.
Ahoile aus dem Süden
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Nach 2 Attributen Filtern

Beitrag von Jan »

Tom hat das oben in seinen Beispielen selbstverständlich immer in der richtigen Reihenfolge geschrieben (bis auf seinen letzten Beitrag, da hat er das im Fließtext umgedreht). Aber um diesen Umstand klar hervorzuheben: Es ist immer wichtig ERST den Scope zu setzen (um auf dem performanten Weg schon mal die Datenmenge runter zu knechten), und DANN erst den Filter auf die nun verringerte Datenmenge zu setzen. Filter sind halt immer um so schneller je geringer die abzuarbeitende Datenmenge ist. Setzt man erst den Filter und dann den Scope mag das mit etwas Glück auch schneller sein als ein komplexer Filter. Aber halt bei Weitem nicht so viel wie erst Scope und dann Filter.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
monokeros
Rookie
Rookie
Beiträge: 7
Registriert: Fr, 12. Nov 2021 15:34
Hat sich bedankt: 3 Mal

Re: Nach 2 Attributen Filtern

Beitrag von monokeros »

Daraus ergibt sich: Der Filter sucht nur innerhalb des zuvor gesetzen Scopes?
Je nach dem würde es dann bei einer großen DB Sinn machen doch einen kombinierten Index zu verwenden, wenn durch den Scope die Datenmenge nur geringfügig kleiner wird.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Nach 2 Attributen Filtern

Beitrag von Tom »

Genau genommen sollte es egal sein, ob man den Filter vor dem Scope setzt oder nicht, denn das Scope enthält ein implizites DbGotop(), der Filter jedoch nicht - er setzt nur eine Bedingung für die Navigation, und solange keine Navigation stattfindet, hat DbSetfilter() überhaupt keine Wirkung. Das müsste man mal ausprobieren.

Und, ja, wenn die Datenmengen sehr groß sind und durch Scopes groß bleiben, sind kombinierte Indexausdrücke sehr sinnvoll. Und es ist grundsätzlich nicht sinnvoll, hier zu sparen, allerdings können viele und sehr komplexe Indexausdrücke beim Erfassen und Bearbeiten von Datensätzen Performancefolgen haben.
Herzlich,
Tom
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Nach 2 Attributen Filtern

Beitrag von Jan »

Moin,

wenn das machbar ist ist ein kombinierter Index mit darauf aufbauenden Scope immer die schnellste Variante. Das wird nur ziemlich schwierig, sobald drei oder mehr Bedingungen da rein sollen - wie willst Du da den TOP und den BOTTOM im Scope bestimmen? Stellenweise ist das schon bei zwei Bedingungen schwierig bis unmöglich. Ich mach sowas schon mal, aber das sind dann ziemliche Verrenkungen. Und immer geht das halt nicht.

Wenn die Filterbedingung nicht einfach nur mit einem Index abbildbar ist, ist Scope + Filter (in dieser Reihenfolge) immer der beste und perfomanteste Weg, wie Tom schon schrieb.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
flanelli
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 151
Registriert: Di, 11. Mai 2010 16:27
Hat sich bedankt: 3 Mal
Danksagung erhalten: 9 Mal

Re: Nach 2 Attributen Filtern

Beitrag von flanelli »

monokeros hat geschrieben: Mi, 01. Dez 2021 10:22 Daraus ergibt sich: Der Filter sucht nur innerhalb des zuvor gesetzen Scopes?
Genau so ist es, ansonsten würde ja ein nachgesetzter Filter die hohe Performance durch das scopen wieder zunichte machen.
monokeros hat geschrieben: Mi, 01. Dez 2021 10:22 Je nach dem würde es dann bei einer großen DB Sinn machen doch einen kombinierten Index zu verwenden, wenn durch den Scope die Datenmenge nur geringfügig kleiner wird.
Das macht nicht nur wegen der Datenmenge Sinn sondern dient auch vielfach zu einem schnellen Switchen der angezeigten bzw. zu bearbeitenden Datenmenge z.b. zwischen Hauptkriterium und Hauptkriterium + Subkriterien.
Ahoile aus dem Süden
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Nach 2 Attributen Filtern

Beitrag von Jan »

Tom,

da warst Du ein wenig schneller als ich ...

Ich habe das nie wirklich ausprobiert. Aber es gibt hier alte Threads die beschreiben, das diese Reihenfolge besser ist.

Das mit dem impliziten DbGoTop() im Scope kann ich leider so nicht unterschreiben. Ich habe das früher schon mehrfach gehabt das der das nicht macht. Und mir daher angewöhnt auch hier, wie bei Filtern, manuell ien DbGoTop() nach dem Scope setzen einzubauen. Dass mag dann doppeltgemoppelt sein, aber ich fühle mich dabei erheblich wohler.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Nach 2 Attributen Filtern

Beitrag von Tom »

@Jan: Das implizite DbGotop() ist vorhanden und wirkt, wirklich. Du kannst dem vertrauen! (Ich musste das in der PostGreS-Version im Frühherbst überall nachtragen, weil die PGDBE kein implizites DbGotop() ausgelöst hat, aber der Bug ist inzwischen gefixt, deshalb ist es jetzt wieder raus, und ich weiß also, wovon ich rede. Wobei - so ganz gefixt ist das noch nicht. Wenn das Scope eine leere Datenmenge erzeugt hat und ein dem Scope entsprechender Datensatz wird eingefügt, verhält es sich immer noch merkwürdig, aber das ist ein anderes Thema.)

Ich baue nachher mal ein Szenario. Möglicherweise ist ein DbSetFilter vor dem DbSetScope sogar performanter. Man weiß nie. 8)
Herzlich,
Tom
monokeros
Rookie
Rookie
Beiträge: 7
Registriert: Fr, 12. Nov 2021 15:34
Hat sich bedankt: 3 Mal

Re: Nach 2 Attributen Filtern

Beitrag von monokeros »

Danke Euch für die Auskunft :thumbright:
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Nach 2 Attributen Filtern

Beitrag von AUGE_OHR »

hi,
Tom hat geschrieben: Mi, 01. Dez 2021 10:57 Ich baue nachher mal ein Szenario. Möglicherweise ist ein DbSetFilter vor dem DbSetScope sogar performanter. Man weiß nie. 8)
solange man mit einem "Skipper" arbeitet "sollte" man SCOPE vor FILTER setzten

IHMO ein SCOPE baut doch auf einem INDEX auf also mache ich zuerst

Code: Alles auswählen

   SEEK(cSEEK)
   IF FOUND()
      SET SCOPE TO cSEEK
      SET FILTER TO WasWeisIch
damit "sollte" er auf dem 1st. Treffer starten
gruss by OHR
Jimmy
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Nach 2 Attributen Filtern

Beitrag von Tom »

Das Seek kannst Du Dir sparen, Jimmy. Scope führt ein Seek aus.

Code: Alles auswählen

DbSetScope(SCOPE_BOTH,<xCondition>)
IF !EoF()
  DbSetFilter({||WasWeißIch()})
Herzlich,
Tom
Antworten