Anmelden

View Full Version : Sql Rekursiv



Seiten : [1] 2 3

tarkusch
04-01-17, 12:27
Hallo,

ich habe eine Bestelldatei(BESTELLP) die 2 relevante Felder(B1NR01, B1NR02) für mich hat.
Der Key von der Datei BESTELLP ist B1NR01.

Falls das Feld B1NR02 befüllt ist, müsste ich mit dieser Nummer so lange lesen bis in diesem Feld Null steht.
Das wäre dann die Orginal-Bestellung mit der ich weiterarbeiten muss.

Bis jetzt wurde das im Rpg so abgebildet


IF B1NR02 <> 0;
DOW B1NR02 <> 0;
CHAIN(N) B1NR02 BESTELLP; // Key ist B1NR01
IF NOT %FOUND;
LEAVE;
ENDDO;
ENDIF;


Ist das möglich in Sql abzubilden?

lg

Fuerchau
04-01-17, 12:47
Die Frage verstehe ich jetzt nicht.
"bis in diesem Feld Null steht" entspricht doch "where Feld = 0".

"Not %Found" ist in SQL " where not exists (select * from blabla where ....)"

tarkusch
04-01-17, 12:55
Mit dem Wert aus dem Feld B1NR02 chaine ich auf die BESTELLP und da steht entweder die Null drin oder ich muss mit der Nummer weitermachen.
Wie weit ich zurückgehen muss ist verschieden.

Fuerchau
04-01-17, 14:15
Die Aufgabe ist schwer zu begreifen: "oder ich muss mit der Nummer weitermachen"?
Welche Nummer ist da gemeint?
Im Moment würde ich "select max(B1NR02) into : MyMax from BESTELLP" annehmen.
Wenn SQLCOD = 0 => erfolgreich, sonst sollte SQLCODE = 100 => keine Daten sein.

B.Hauser
04-01-17, 14:19
Nochmal zum Verständnis:
In Deiner Bestell-Datei sind für B1BNR01 mehrere gleiche Werte. In B1BNR02 sind für den gleichen B1BNR01-Schlüssel-Wert mehrere verschiedene Werte und u.a. ist auch mindestens 1x der Wert 0 zu finden (kein NULL-Wert?!).
Du versuchst für einen bestimmten Schlüssel den Satz mit der 0 zu finden?

Sofern es das ist, das Du das willst, kann es mit SQL ganz einfach gelöst werden (da braucht man auch kein verschachteltes Sub-Select)


Select Fld1, Fld2, ... FldN
From YourTable
Where B1BNR01 = 'YOURVALUE' and B1BNR02 = 0;

Mir ist übrigens auch schleierhaft, warum Du deinen Key nicht einfach um ein zweites Schlüssel-Feld erweiters (bzw. eine LF oder besser einen SQL Index anlegst mit 2 Schlüssel-Feldern. Dann könntest Du den Satz auch mit native I/O direkt greifen.

Solltest Du stattdessen tatsächlich eine Rekursion wollen, d.h. mit dem in B1BNR02 gefundenen Wert muss ein Zugriff auf B1BNR02 erfolgen und der letzte Wert in B1BNR02 ermittelt werden, könnte die Abfrage evtl. wie folgt aussehen (Mindest-Release 7.1)


Select *
From YOURTABLE
Start With B1BNR01 = 'YOURVALUE'
Connect By Prior B1BNR01 = B1BNR02
Order By Level Desc
Fetch First Row Only;

Birgitta

Fuerchau
04-01-17, 14:28
So wie es aussieht könnte es sich um eine "verkettete Liste" handeln.
D.h., das Feld B1NR02 verweist "rekursiv" auf sich selbst, bis der letzte Satz keinen weiteren Verweis mehr hat, z.B.:
1 => 5 => 12 => 0
2 => 3 => 7 => 11 => 0
17 => 4 => 6 => 35 => 0
Dies ist mit einer SQL-Methode hier tatsächlich nicht zu lösen sondern ebenso mittels einzelner "Select into " zu lösen. Ein Cursor ist nicht erforderlich.

Allerdings solltest du dir hier tatsächlich ein anderes Model entwickeln, denn solche Strukturen sind SQL-technisch nicht vernünftig und schon gar nicht performant auswertbar.

tarkusch
04-01-17, 14:29
Sorry, aber mit der Formulierung habe ich mir schwer getan.
J
a ich muss mit der Nummer die ich ermittelt haben wieder weitermachen.
Schuss ist sobald die B1NR02 0 ist.
Der Primary-Key der Datei ist B1NR01



B1NR01 B1NR02
25000 24800
24800 24795
24795 0

tarkusch
04-01-17, 14:43
Danke vielmals,

Connect By Prior scheint die Lösung zu sein.
Werde mal sehen wie performant das ist.
lg

Fuerchau
04-01-17, 15:00
Da benötigst du doch wieder einen Cursor und musst alle Sätze bis zum letzten lesen.
Oder du packst das dann in eine derived table:
select * from (
select .... connect by ....
) hugo
where B1NR02 = 0
da du ja nur den letzten benötigst.
Gelesen werden muss aber trotzdem alles und ist eben ein eher schlechtes Datenmodell.

B.Hauser
04-01-17, 15:19
Da benötigst du doch wieder einen Cursor und musst alle Sätze bis zum letzten lesen.

Braucht er nicht!
Wenn er die Lösung so nimmt wie angegeben, benötigt er lediglich einen SELECT ... INTO, da in dem Beispiel der letzte Satz ausgegeben wird.