OrdCreate()

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

Moderator: Moderatoren

Antworten
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14658
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

OrdCreate()

Beitrag von Jan »

Mal wieder eine Frage der vermutlich einfacheren Art: Kann ich eigentlich in OrdCreate() ein descend unterbringen?

Jan
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 »

Ja.
Probiere es doch mal mit Descend(...)
In der Hilfe zu der Funktion findest Du auch beschrieben, wie Du dann suchen musst (nämlich auch mit Descend(...))

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

Re: OrdCreate()

Beitrag von AUGE_OHR »

hi,
Jan hat geschrieben: Kann ich eigentlich in OrdCreate() ein descend unterbringen?
Nein, aber ich weiss was du willst :)

Du musst VORHER mit OrdCondSet() die Bedingung setzten welche
bei OrdCreate() dann ausgeführt wird.

Ich sehe mir solche Sachen immer im PPO Code an, also einfach mal
deinen INDEX ON Audruck mit Xpp /P compilieren.

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,
warum soll das nicht gehen??

Code: Alles auswählen

OrdCreate( "MYINDEX", "Verkauf", "Str(Descend(ANZAHL),10)+Upper(NACHNAME+VORNAME)" )
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 »

hi,
Martin Altmann hat geschrieben: warum soll das nicht gehen??

Code: Alles auswählen

OrdCreate( "MYINDEX", "Verkauf", "Str(Descend(ANZAHL),10)+Upper(NACHNAME+VORNAME)" )
ich denke schon das es so gehen müsste ... aber die PPO sieht anders aus

Code: Alles auswählen

INDEX ON Str(Descend(ANZAHL),10)+Upper(NACHNAME+VORNAME) TAG Verkauf TO MYINDEX

ergibt als PPO

ordCondSet( ,  ,, , ,  , RECNO(), , , , , , ,  ) 
ordCreate("MYINDEX",;
                "Verkauf",;
                "Str(Descend(ANZAHL),10)+Upper(NACHNAME+VORNAME)",;
                _EarlyBoundCodeblock({|| Str(Descend(ANZAHL),10)+Upper(NACHNAME+VORNAME)}), ,
.F. )
keine Ahnung ob es einen Unterschied macht, aber man hört ja immer
wieder von Problemem mit Descend(). Ich verwende immer noch den
INDEX ON Style und hab keine Probleme mit Descend().

gruss by OHR
Jimmy
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14658
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Beitrag von Jan »

Tja, irgendwas läuft da aber falsch.

Zum Einen finde ich es kompliziert, sowohl bei der Indexerstellung als auch in der Anwendung immer das Descend() einzubauen. Warum muß das sein? Bei INDEX ON geht das doch auch anders. Und ich hatte eher an etwas in dieser Richtung gedacht. Auch, weil die Onlinehilfe sagt, daß es mit dem aus INDEX ON bekannten DESCENDING schneller gehen würde.

Aber egal: Wenn ich das so mache, dann kommt im Browse etwas falsches an. Die Codezeilen sehen so aus:

Indexerstellung (oFortschritt ist der Laufbalken für die Fortschrittsanzeige):

Code: Alles auswählen

ORDCREATE((MEMVAR->gcSchauPfad + "Tiere"), "Geschlecht", "Descend(FIELD->geschlecht)", {||oFortschritt:increment(), FIELD->geschlecht}, .F.)
Und die Browse-Spalten:

Code: Alles auswählen

{|| AllTrim(Str(Descend(tiere->geschlecht)))}
Als Geschlecht kommen zum Einsatz 0,1 und 1,0. Ich muß die 1,0 vor die 0,1 sortiert bekommen. Mache ich das so wie oben gezeigt dann habe ich im Browse ein -0,1 und ein -1,0 stehen! Was nun wirklich nicht das gewünschte Ergebnis ist.

Jan
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 »

Hallo Jan,
Du unterliegst da wohl einem „Denkfehler“.

Die Reihenfolge einer Index-Datei und Datenanzeige von Feldwerten im „Browse“ sind 2 getrennte Paar Schuhe.

Ein

Code: Alles auswählen

{|| AllTrim(Str(tiere->geschlecht))}
würde schlichtweg nur den Feldinhalt (0/1)anzeigen.

Ich würde nichtssagende Werte eher wie folgt darstellen:

Code: Alles auswählen

{|| IIF(tiere->geschlecht == 0, „M“, „W“)}
Beste Grüße
Olaf

PS: Nur in Verbindung mit einem "Seek" oder beim Setzen eines Filters wäre ein "Descend(tiere->geschlecht)" erforderlich.
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14658
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Beitrag von Jan »

Hallo Olaf,

nette Idee, hatte ich auch schon. Aber die Züchter bestehen auf ihrem altgewohnten 1,0 und 0,1. Kann man nichts machen :(

Aber um auf das Sortierthema zurückzukommen: Im Browse kann ich das umgehen, indem ich den nach einem anderen Kriterium sortiere. Finde ich dennoch unbefriedigend, denn was wäre, wenn ich nun unbedingt dieses Sortierkriterium haben müsste?

Aber ich muß die Tiere durchnummerieren. Und dabei komme ich um das Geschlecht nicht drumrum. Und ich muß definitiv 1,0 vor 0,1 stehen haben (alles Chauvinisten, diese Züchter :-) ) Ich gehe also auf den Anfang der Datenbank, auf die ich den entsprechenden Index ausgewählt habe, und kämpfe mich da dann durch. Wo bitte schön kann ich denn da das Descend() lassen? Denn ansonsten habe ich auch da die falsche Reihenfolge.

Um ehrlich zu sein: Das Thema ist mir gewaltig gegen den Strich gegangen. Ich mach das jetzt einfach andersherum, mache ein DbGoBottom() und skippe mich dann mit DbSkip(-1) nach oben durch. Dann stimmt das wieder, und in diesem Fall ist das auch überhaupt kein Problem. Und wie oben gesagt, den Browse habe ich jetzt anders sortiert, ich muß mir nur noch eine saubere Begründung den Züchtern gegenüber einfallen lassen.

Aber es muß doch eigentlich auch anders gehen. Wozu ist denn sonst Descend() gut, wenn ich das weder im Browse noch beim ganz normalen skippen nutzen kann? Warum kann es bei einem ganz normalen OrdSetFocus() kein Descend() geben?

Und ich verstehe immer noch nicht, warum ich sowohl bei der Indexerstellung als auch bei der Nutzung dieses Index ein Descend() einbauen muß. Ich dachte eigentlich immer, wenn ich den Index absteigend erstellt habe, dann ist er das auch. Wie eben halt mit dem DESCENDING bei INDEX ON. Da geht es ja auch. Nur nicht bei OrdCreate().

Jan
Benutzeravatar
urbi
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 142
Registriert: So, 26. Mär 2006 18:47
Wohnort: 76185 Karlsruhe
Kontaktdaten:

Beitrag von urbi »

Hallo Jan,

ich hatte voe einiger Zeit das gleiche Problem,
und gelöst mit:

OrdCreate( path+"anum.ntx",, "100000-RECNO()",{||100000-RECNO() } )

Gruss
Rainer
urbi
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 »

Moin Jan,
Die jeweilige Vieh-Nr. ist doch sicherlich nur einmal vergeben.

Um absteigend nach der Vieh-Nr. zu sortieren:

{|| Descend( TIERE-NR ) }

Um nach Geschlecht (absteigend) + NR (absteigend) zu sortieren:

{ ||(DESCEND( Str(TIERE->GESCHLECHT)) + DESCEND( Str(TIERE->NR))}

Um nach Geschlecht (absteigend) + NR (aufsteigend) zu sortieren:
{ || (DESCEND( Str(TIERE->GESCHLECHT))) + str(TIERE->NR)}

Du konntest auch das Geschlecht (0/1) in einem C-Feld abspeichern. Dann würde der Index-Aufbau wie folg aussehen:

//Geschlecht (absteigend) + NR (aufsteigend):
{ ||DESCEND( TIERE->GESCHLECHT) + DESCEND( Str(TIERE->NR)))}

//Um nach Geschlecht (absteigend) + NR (aufsteigend) zu sortieren:
{ || DESCEND( TIERE->GESCHLECHT) + str(TIERE->NR)}
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14658
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Beitrag von Jan »

Moin, moin, alle zusammen,

Olaf: Die eindeutige Nummer ist eigentlich die Käfignummer. Und da kommen die 1,0 vor den 0,1. Was bedeutet, ich muß erst sortieren, bevor es da eine Nummer gibt. Natürlich könnte ich noch eine andere eindeutige Nummer mitführen, aber wäre es nicht etwas zu aufwändig, eine eindeutige Nummer mit all den dazu passenden Problemen (ich erinnere mich da z. B. an die Fragestellung hier im Forum mit der eindeutigen Nummerierung), nur weil ich einen absteigenden Index haben möchte? Das kann doch irgendwie nicht ganz der Sinn der Sache sein.

Rainer: Nette Idee. Ich kann mich jetzt, wo Du es sagst, erinnern, daß es da mal einen Forenbeitrag zu gab.

Aber es geht doch inzwischen, da ich ja einen für diesen Fall persönlich passenden Workaround gefunden habe, mehr um die Problematik ansich: Warum funktioniert Descend() in einigen Bereichen nicht, und da, wo es funktioniert, nur sehr umständlich? Sollte es nicht eigentlich ganz einfach gehen? Oder gibt es einen Grund dafür, der sich mir einfach nur noch nicht erschlossen hat?

Jan
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21200
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hallo Jan,

nur mal so kurz zum Verständnis:

1) Die Züchter wollen 0,1
2) Olaf schlägt "W" und "M" vor.

Wann wollen die Züchter 0,1? Bei der Eingabe? Bei der Anzeige? Was spricht dagegen alles jeweils zu konvertieren? Die Züchter bekommen ihr 0,1 bei der Anzeige und Du arbeitest intern mit "M" und "W" ? Du bist doch der Programmierer und bestimmst, was am Bildschirm steht. Also bau ihnen das doch so, wie sie es wollen. Was Du intern machst, ist doch Dein Bier.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14658
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Beitrag von Jan »

Hallo Manfred,

die Züchter wollen 0,1 (="w") und 1,0 (="m"). Und zwar immer und überall. Alle Eingaben, alle Ausgaben, egal ob Bildschirm oder Drucker.

Und klar, ich könnte das intern ummünzen.

Aber wie ich oben schon gesagt habe: Es läuft ja jetzt. Nicht so, wie ich das eigentlich mir vorgestellt habe, aber OK. Die Frage ist jetzt nur noch: WARUM? Warum funktioniert Descend() nur halb (in meinen Augen)?

Aber wo ich Dich gerade dran hab: Wie kommst Du nach Berlin? Andreas und ich haben schon Sitzplätze, zufällig auch fast die gleiche Reihe. Aber ich fürchte, für Dich wäre das ein zu großer Umweg mit dem Zug über uns, oder? Ansonsten wär das eine tolle Fahrt mit der halben XUG Osnabrück zusammen in einem Zug nach Berlin :-)

Jan
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21200
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi Jan,

wie schon erwähnt, ich komme mit dem PKW. Das ist mir der liebste Weg, weil ich dann total unabhängig bin.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
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 »

:wave: Jan,
DESCEND(..): Wenn Du dies bei OrdCreate() nutzte, mußt Du es auch bei DbSeek() verwenden!
Es ist und war nie die Rede davon, es bei der Ausgabe von Daten verwenden zu müssen!
Also:
Mach wie bisher Dein

Code: Alles auswählen

ORDCREATE((MEMVAR->gcSchauPfad + "Tiere"), "Geschlecht", "Descend(FIELD->geschlecht)", {||oFortschritt:increment(), FIELD->geschlecht}, .F.)
aber nur

Code: Alles auswählen

{|| AllTrim(Str(tiere->geschlecht))}
Sollte wie gewünscht gehen, oder nicht?

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
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 »

Descend ist gar nicht so kompliziert, wenn man weiß, welche Werte ein DesCend() erzeugt. Die Online-Hilfe von xBase sagt m.E. alles Wesentliche aus.

Ein Problem kommt meist auf, wenn ein Decend-Index sich aus 2 Feldern zusammen setzt.


Beispiel:

Kühe sollen nach Käfig geordnet jeweils mit einem absteigenden Preis gelistet werden, d.h., die teuerste Kuh je Käfig soll an erster Stelle stehen.

Legen wir mal folgende Daten zugrunde:

Code: Alles auswählen

1.	K = „A“, Preis = 1000
2.	K = „A“, Preis = 500
3.	K = „A“, Preis = 100
Wie muss nun der Index aufgebaut sein?

Der Index-Ausdruck

Code: Alles auswählen

{|| FIELD->K + Str(Descend(FIELD->PREIS),5) 
führt für die Datensätze zu folgenden Ergebnis:

Code: Alles auswählen

„A“ + „-1000“ = „A-1000“
„A“+ „ -500“   = „A -500“
„A“+ „ -100“   = „A -100“

Da wiederum die Ergebnisse des Index-Ausdrucks aufsteigend entsprechend der ASCII-Reihenfolge abgelegt werden, ergibt sich in der INDEX-Datei folgende Reihenfolge:

Code: Alles auswählen

„A -100“
„A -500“
„A-1000“

Der Index-Ausdruck

Code: Alles auswählen

{|| FIELD->K + Descend(Str(FIELD->PREIS,5)) 
führt auch nicht zum gewünschtem Ergebnis, weil sich keine streng monotone Werte-Reihenfolge aufgrund der ASCII-Sortierung ergibt.

Wir brauchen jedoch folgende Reihenfolge:

Code: Alles auswählen

„A1000“
„A500“
„A100“

Mit dem Ausdruck

Code: Alles auswählen

 {|| ( FIELD->A + Transform( 999999.99 - FIELD->PREIS,'@L0 999999.99')}
wird folgende (ASCII-) Reihenfolge –erreicht:

Code: Alles auswählen

“A998999,99”
“A999499,99”
“A999899,99”
Die Reihenfolge entspricht nun der oben genannten Aufgabenstellung.

Ich hoffe, das die Erläuterungen die Descend-Funktion ein wenig entmystifizieren.

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 »

Hi Jan,

ich meine das mit dem descend() hatten wir schon einmal ausführlich.
INDEX ON IrgendEinFeld DESCEND funktioniert - soweit ich mich erinnern kann - immer richtig. (DBSeek() lass ich jetzt mal außen vor)

Bei einem Feld und damit einem Datentyp kann Xbase++ zuverlässig ermitteln, was es aus einem Datenwert machen muss um die Reihenfolge passend zu bekommen. Beim Suchen muss man dann natürlich - wie bei jeder anderen Manipulation im Indexaufbau - auch das Descend verwenden, da intern ja nicht der original Wert steht.

Das Problem tritt dann aber - wie Olaf an Beispielen gezeigt hat - auf, wenn man selbst mehrere Datentypen in einen String zwingt und dann erwartet dass die Funktion - automatisch - weiß was man will.

Ich würde für solches immer eine eigene Funktion basteln, wobei numerische Werte über die schon erwähnte Abziehmethode zu konvertieren sind - dann weiß man auch was man braucht und der Funktion übergibt man die Parameter (Felder) ohne jedesmal die ganze Litanai schreiben zu müssen. Bei numerischen Parametern würde ich die Maximale Länge angeben ...

Code: Alles auswählen

function MySort(cFeld1, nFeld2,nMaxLen,nMaxDec, lFeld3 )
   local nMaxWert, cIndexWert 
   DEFAULT nMaxLen TO 18
   DEFAULT nMaxDec TO 0
   
   nMaxWert := val("1"+replicate("0",nMaxLen))
   cIndexWert := cFeld1+;
                         right( strzero(nMaxWert-nFeld2,;
                                             nMaxLen,nMaxDec) ,nMaxLen)+;
                         iif(lFeld3,"1","0")
return cIndexWert
Da man den String selbst zusammenbaut, kann man so wesentlich besser abschätzen wie die Sortierung ausfallen wird. Hier ist Descend() nur auf den numerischen Wert angewandt, will man cFeld1 auch umsetzen kann man dafür die origial descend() Funktion verwenden, bei reinen Strings funktioniert sie gut. Bei Logischen Werten muss man nur 0 und 1 tauschen ...

Bei den häutigen Plattengrößen und Datenmengen halte ich es aber wirklich für besser ein eigenes Indexfeld mitzuführen - man muss es ja nicht anzeigen ;-)
Gruß
Hubert
Antworten