Seite 1 von 1

Nach 2 Attributen Filtern

Verfasst: Mo, 29. Nov 2021 13:31
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.

Re: Nach 2 Attributen Filtern

Verfasst: Mo, 29. Nov 2021 13:37
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

Re: Nach 2 Attributen Filtern

Verfasst: Mo, 29. Nov 2021 14:28
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.

Re: Nach 2 Attributen Filtern

Verfasst: Mo, 29. Nov 2021 14:37
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.

Re: Nach 2 Attributen Filtern

Verfasst: Di, 30. Nov 2021 15:50
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.

Re: Nach 2 Attributen Filtern

Verfasst: Di, 30. Nov 2021 16:56
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

Re: Nach 2 Attributen Filtern

Verfasst: Mi, 01. Dez 2021 10:22
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.

Re: Nach 2 Attributen Filtern

Verfasst: Mi, 01. Dez 2021 10:43
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.

Re: Nach 2 Attributen Filtern

Verfasst: Mi, 01. Dez 2021 10:43
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

Re: Nach 2 Attributen Filtern

Verfasst: Mi, 01. Dez 2021 10:45
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.

Re: Nach 2 Attributen Filtern

Verfasst: Mi, 01. Dez 2021 10:47
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

Re: Nach 2 Attributen Filtern

Verfasst: Mi, 01. Dez 2021 10:57
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)

Re: Nach 2 Attributen Filtern

Verfasst: Mi, 01. Dez 2021 11:14
von monokeros
Danke Euch für die Auskunft :thumbright:

Re: Nach 2 Attributen Filtern

Verfasst: Mi, 01. Dez 2021 13:43
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

Re: Nach 2 Attributen Filtern

Verfasst: Mi, 01. Dez 2021 14:53
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()})