Problem mit INDEX-Tag bei absteigender Sortierung

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

Moderator: Moderatoren

Antworten
Benutzeravatar
Lewi
1000 working lines a day
1000 working lines a day
Beiträge: 830
Registriert: Di, 07. Feb 2006 14:10
Wohnort: Hamburg
Danksagung erhalten: 2 Mal

Problem mit INDEX-Tag bei absteigender Sortierung

Beitrag von Lewi »

Hallo miteinander!

Folgendes Problem: Ich möchte die Datensätze sortiert nach IDNR (Datentyp: „C“ und Preis (Datentyp „N“ , wobei ich eine absteigende Sortierung haben möchte. (xBase 1.82)

Für eine aufsteigende Sortierung nutze ich einen Index mit folgendem Tag-Aufbau:

Code: Alles auswählen

FIELD->IDNR + Transform( FIELD->PREIS, '@L0 999,999.99')
Die Reihenfolge ist wie gewünscht:
  • 4,000.00
    4,500.00
    5,000.00
    5,500.00
    7,800.00
    7,900.00
    7,950.00
Wenn ich nun den kontrollierenden Index für ein absteigende Sortierung wie folgt aufbaue:

Code: Alles auswählen

FIELD->IDNR + DESCEND( Transform( FIELD->PREIS, '@L0 999,999.99') )
erhalte ich eine Reihenfolge, die nicht streng absteigend ist:
  • 7,800.00
    7,950.00
    7,900.00
    5,500.00
    5,000.00
    4,500.00
    4,000.00
Mal abgesehen davon, dass mich die Reichenfolge „verblüfft“, wo liegt mein „Denkfehler“ beim Aufbau des TAGS?

Ach ja, weder ein REORG noch eine Abänderung des Wertes „7,800.00“ auf z.B. „7,820.00“ ändert etwas an der Reichenfolge.

Gruß, Olaf
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Olaf,
DESCEND hat so seine Probleme (derzeit)!
Bau Dir Dein eigenes DESCEND:

Code: Alles auswählen

FIELD->IDNR + Transform( 999999.99 - FIELD->PREIS, '@L0 999,999.99') )
Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hi,

eventuell stören die eingefügten Tausendertrennzeichen.
Versuche mal ob str(descend(nWert),x,y) besser funktioniert.
Gruß
Hubert
Benutzeravatar
Lewi
1000 working lines a day
1000 working lines a day
Beiträge: 830
Registriert: Di, 07. Feb 2006 14:10
Wohnort: Hamburg
Danksagung erhalten: 2 Mal

Beitrag von Lewi »

Bei der Funktion DESCEND() scheint es tatsächlich wohl unter xBase 1.82 einen Bug zu geben.

Wenn ich eine Testdatei wie folgt indiziere:

Code: Alles auswählen

ordCondSet( ,  ,, , ,  , RECNO(), , , , .F. )   // DESCENDIG Methode
ordCreate("TEST.CDX", "1", , {|| FIELD->IDNR + Transform( 999999.99 - FIELD->PREIS,"@L0 999999.99")}, , .F. )
dann erfolgt zwar eine korrekte absteigende Reihenfolge, allerdings wird über Seek( DESCEND( “1”) [1=steht für eine IDNR, alphanumerisch] kein Datensatz gefunden. Die wäre aber wiederum erforderlich um die gewünschte Listenausgabe zu erhalten.


Wenn ich einen INDEX Tag mittels Descend() eine absteigende Sortierung über

Code: Alles auswählen

ordCreate("TEST.CDX", "1", , {|| DESCEND(FIELD->IDNR + Transform( 999999.99 - FIELD->PREIS,"@L0 999999.99"))}, , .F. )
erreichen möchte, dann führt dies zu einer fehlerhaften Reihenfolge.


Mein turn arround basiert auf Martins Lösungsansatz:

Code: Alles auswählen

ordCreate("TEST.CDX", "5", , {|| FIELD->IDNR + Transform( 999999.99 - FIELD->PREIS,"@L0 999999.99")}, , .F. )

Hubert, Dein Lösungsvorschlag

Code: Alles auswählen

str(descend(nWert),x,y
greift nicht, da der Ausdruck „Str(Descend(FIELD->PREIS),8,2)“ zu einer negativen Zahl (ohne Str() ) führt und die Sortierung demnach aufsteigend wäre (z.B. -4000 < -2000 )


Gruß, Olaf
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9367
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 102 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Beitrag von Tom »

Hallo, Olaf.

Code: Alles auswählen

Index on (99999999999 - db->wert) to index.ntx
(ggf. noch mit Transform oder Str)

Nicht elegant, funzt dafür immer.
Herzlich,
Tom
Benutzeravatar
Lewi
1000 working lines a day
1000 working lines a day
Beiträge: 830
Registriert: Di, 07. Feb 2006 14:10
Wohnort: Hamburg
Danksagung erhalten: 2 Mal

Beitrag von Lewi »

Tom, ich brauche für einige Listen (mit FRAX) einen zusammengesetzten Index aus "IDNR" + "PREIS".
Ob nun der INDEX auf einem Tag oder einer separaten Index-Datei basiert scheint mir im Zusammenhang mit dem DESCEND() Problem weniger "lösungsrelvant" zu sein.

Ist Alaska das Problem mit der Descend() Funktion bekannt???

Gruß, Olaf
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Lewi hat geschrieben:Hubert, Dein Lösungsvorschlag

Code: Alles auswählen

str(descend(nWert),x,y
greift nicht, da der Ausdruck „Str(Descend(FIELD->PREIS),8,2)“ zu einer negativen Zahl (ohne Str() ) führt und die Sortierung demnach aufsteigend wäre (z.B. -4000 < -2000 )
Genau das ist gewünscht, und gleichzeitig das Problem.

descend(400) -> -400
descend(500) -> -500

Wird nun der Index nur auf die Descend(nr) gelegt, stimmt die Sortierung, da nummerisch die Reihenfolge so ist:

-500
-400

was wir ja wollten.

Wenn man aber STR() dazu mixt, wird nicht mehr nummerisch sondern linksbündig String verglichen.

A-400 // kleiner bei Textvergleich.
A-500

Ob dies nun ein Fehler bei der Umsetzung von descend() ist lasse ich mal dahingestellt. Zumindest die Dokumentation sollte erklären, dass nummerische Variablen nicht mit Descend und str() verwendet werden dürfen. Descend() setzt einfach das - BIT. Es bleibt also nichts anderes übrig, als TOMs oder Martins Weg einzuschlagen.
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Lewi hat geschrieben:Tom, ich brauche für einige Listen (mit FRAX) einen zusammengesetzten Index aus "IDNR" + "PREIS".
Ob nun der INDEX auf einem Tag oder einer separaten Index-Datei basiert scheint mir im Zusammenhang mit dem DESCEND() Problem weniger "lösungsrelvant" zu sein.
Für solche temporären Listen hat Stefen den SORT Befehl vorgeschlagen.
Wenn man mit SetScope die Grenzen eng setzt, dann in SORT mit der FOR Klausel den Rest ausfiltert, nur die Felder nimmt die man wirklich braucht und flexibel sortiert, wäre das sehr schnell. Eine sortierte DBF macht auf jeden Fall bei Fremdprodukten weniger Ärger als ein Index.

Nur so als Idee ...
Gruß
Hubert
Benutzeravatar
Lewi
1000 working lines a day
1000 working lines a day
Beiträge: 830
Registriert: Di, 07. Feb 2006 14:10
Wohnort: Hamburg
Danksagung erhalten: 2 Mal

Beitrag von Lewi »

Logisch

Ich bin dem Problem noch einmal auf dem Grund gegangen und zum Ergebnis gekommen, dass die Funktion DESCEND() in Verbindung mit Index-Ausdrücken zur Erzeugung von absteigenden Indexen im Zusammenhang mit alphanumerischen + numerischem Feld nicht geeignet ist.

Der Grund dafür liegt nicht in einer fehlerhaften Implementierung der DESCEND() Funktion sondern darin, dass für ein Index-Tag bzw. eine Index-Datei bei der Nutzung von einem numerischen Feld in Verbindung mit einem alphanumerischen Feld der Indexausdruck immer ein String zurück geben muss. Somit erfolgt die Reihenfolge über einen String-Vergleich.

Die nachfolgenden Beispiele sollen dies verdeutlichen. Aus Gründen der Übersichtlichkeit verzichte ich auf ein über mehrere Felder zusammengesetzten Indexausdruck, sondern betrachte ich Nachfolgenden ein einfaches PREIS-Feld.
  • FIELD->PREIS
    1
    4000
    7000
    12000
Bei String-Vergleichen gelten folgende Bedingungen:

Aufsteigende Reihenfolge: „ “ < „-„ < „0“ oder chr(32) < chr(45) < chr(48 )
Absteigende Reihenfolge: „0“ > „-„ > „ „ oder chr(48 ) > chr(45) > chr(32)

Ein Index mit Str( FIELD->PREIS,6,0) ergibt über den Stringvergleich folgende Reihenfolge:
  • „_____1“
    „__4000“
    „__7000“
    „_12000“
Ein Index unter Verwendung von Transform( FIELD->PREIS, „@L0 999999“) führt über den String-Vergleich zu folgender Reihenfolge:
  • „000001“
    "004000"
    "007000"
    "012000"
Ein Index unter Verwendung von Str( Descend(xWert), 6,0) führt über den String-Vergleich zu folgende Reihenfolge:
  • „____-1“
    „_-4000“
    „_-7000“
    „-12000“
Ein Index unter Verwendung von Transform( DESCEND(FIELD->PREIS), „@L0 999999“) führt über den String-Vergleich zu folgender Reihenfolge:
  • "-12000"
    „-04000“
    „-07000“
    „-00001“
Somit bleibt festzuhalten, dass Str(Descend( nValue ),x,y) bzw. Transform( Descend(nValue), „@L0 999999.99“) nicht geeignet ist, um eine absteigende Sortierung zu erhalten.

Gruß, Olaf

PS: Bedingt durch die proportionale Schrift habe ich zur besseren Visualisierung Leerzeichen mit einem Unterstrich aufgeführt.
Zuletzt geändert von Lewi am Di, 20. Mär 2007 7:44, insgesamt 1-mal geändert.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Beitrag von AUGE_OHR »

hi,
Lewi hat geschrieben: Somit bleibt festzuhalten, dass Str(Descend( nValue ),x,y) bzw. Transform( Descend(nValue), „@L0 999999.99“) nicht geeignet ist, um eine absteigende Sortierung zu erhalten.
und was ist mit STRZERO() ?

gruss by OHR
Jimmy
Benutzeravatar
Lewi
1000 working lines a day
1000 working lines a day
Beiträge: 830
Registriert: Di, 07. Feb 2006 14:10
Wohnort: Hamburg
Danksagung erhalten: 2 Mal

Beitrag von Lewi »

Hi Jimmy,
StrZero( nWert,6,0) ist gleichzusetzen mit Transform( nWert, "@L0 999999" ).
Insofern ist Dein Hinweis bereits berücksichtigt.

Gruß, Olaf
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Beitrag von AUGE_OHR »

hi,
Lewi hat geschrieben: Bei der Funktion DESCEND() scheint es tatsächlich wohl unter xBase 1.82 einen Bug zu geben.
das selbe passiert auch mit der v1.9x wenn man über einen String geht.

Entgegen den Tip von Tom und Martin würde ich aber nicht "9999999 -"
nehmen sondern das ganze, per "OffSet", ins "positive" bringen also
1.000.000 (bei "N",6 ) und das ganze per #define

Code: Alles auswählen

#define DesOffSet 1000000

FUNCTION MAIN
LOCAL i

   SET COLLATION TO GERMAN

   IF .NOT. FILE("DESDBF.DBF")
      CRE_SETUP("DESDBF.DBF")
   ENDIF

   USE DESDBF EXCLUSIV
   ZAP

   FOR i:= -100 TO 100
      APPEND BLANK
      REPLACE IDNR  WITH "AAAAAA"
      REPLACE PREIS WITH i
   NEXT
   INDEX ON DESDBF->IDNR+STRZERO( (DESDBF->PREIS+DesOffSet),7 ) TO DESNTX

   SEEK( "AAAAAA"+STRZERO(0+DesOffSet,7) )
   BROWSE()

RETURN NIL

FUNCTION CRE_SETUP(datei)
LOCAL field_list:={}
    aadd(field_list,{"IDNR"    ,"C",6,0})
    aadd(field_list,{"PREIS"   ,"N",6,0})

    dbcreate(datei,field_list)
RETURN NIL
gruss by OHR
Jimmy
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Jimmy,
AUGE_OHR hat geschrieben:Entgegen den Tip von Tom und Martin würde ich aber nicht "9999999 -" nehmen sondern das ganze, per "OffSet", ins "positive" bringen also 1.000.000 (bei "N",6 ) und das ganze per #define
nur dass es damit latürnich nicht absteigend, sondern nach wie vor aufsteigend sortiert ist :wink:

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12909
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Beitrag von AUGE_OHR »

moin,
Martin Altmann hat geschrieben: nur dass es damit latürnich nicht absteigend, sondern nach wie vor aufsteigend sortiert ist :wink:
uuups ... da hab ich es genau "anderrum" gemacht, aber kein Problem :

Code: Alles auswählen

   INDEX ON DESDBF->IDNR+DESCEND(STRZERO( (DESDBF->PREIS+DesOffSet),7 )) TO DESNTX

   SEEK( "AAAAAA"+DESCEND(STRZERO(16+DesOffSet,7)) )
so nun ist das DESCEND() drin und funktioniert wohl wie gewünscht, oder ?

gruss by OHR
Jimmy
Antworten