PDA

View Full Version : SQL Techniken in Verbindung mit Subfile



Seiten : [1] 2 3

harkne
29-04-21, 11:06
Hallo zusammen,

ich versuche mal meine Problematik zu erklären.

Auf meiner Subfile kann man sortieren und positionieren oder auch z.B. F5 für aktualisieren drücken.

Die Subfile ist (ich nenne das volldynamisch) SFLSIZ=SFLPAG bei mir beide 15

Beim Positionieren und bei F5 hole ich mir den 1. Satz der Subfile und gebe beim SQL WHERE mit an " ... AND FELD1 >= wert AND FELD2 >= wert". Ich habe berücksichtigt dass der eindeutige Schlüssel immer mit dabei ist.

Bisher noch kein Problem

Lesen 15 Sätze, Subfile füllen und anzeigen.

Vorwärts blättern Subfile clearen, Lesen 15 Sätze, Subfile füllen und anzeigen.

Immer noch kein Problem.

Blättert er zurück

Rückwärts Lesen 15 Sätze Subfile füllen und anzeigen.
Wäre soweit kein Problem bis ich an den ersten Satz des abgesetzten SQL komme.

Da ich ja mit >= gearbeitet habe gibt es jetzt keinen vorherigen Satz mehr, was ja von den Daten her nicht stimmt.

Die einzige Möglichkeit die mir jetzt eingefallen ist, ist ich muss das gleiche SQL mit < absetzen und mit DESCEND sortieren.

Hat irgend jemand noch Ideen?

Es soll weiterhin SQL bleiben und es sollen auch nur die Daten eingelesen werden die angezeigt werden.

Viele Grüße Harald

mk
29-04-21, 11:17
609

Es gibt auch weitere SQL Fetch Möglichkeiten.
Vielleicht hilft es

B.Hauser
29-04-21, 11:30
Wenn Du die "Seiten-Nr." kennst, kannst Du mit Limit/Offset (im Declare bzw. nach dem SELECT-Statement) die entsprechenden Datensätze direkt abrufen.

Birgitta

BenderD
29-04-21, 11:54
... prepared statement und für jeden Leseblock neuer open using mit anschließendem Blockfetch und
close.

D*B

Fuerchau
29-04-21, 12:03
Einfacher ist ein Scrollable Cursor (wenn es die Abfrage erlaubt).
Mittels "Fetch relative +/- N" kannst du dann um 2 x N (N = Anzahl/Seite) rückwärts positionieren und die SFL neu füllen.
Die Daten werden dann auch aktualisiert.

Limit/Offset ist manchmal halt keine gute Lösung, da durch Offset die Anzahl Zeilen ja erst überlesen werden müssen. Bei den 1. 10 Seiten gehts vielleicht noch, hängt allerdings von der Komplexität der Where-Klausel und den verfügbaren Indizes ab.

Ins besonders wenn du die Order-By-Klausel noch dynamisierst und keine passenden Indizes vorhanden sind.

harkne
29-04-21, 12:22
Mein Problem war ja eigentlich dass ich beim Positionieren mit >= gearbeitet habe und dann der Scroll Cursor vorher gar nichts mehr hat zum lesen. Aber ich habe mich jetzt auch davon verabschiedet und setze einfach das SQL ab und versuche dann mit einem eurer Vorschläge an die entsprechende Stelle zu gelangen, wobei mir LIMIT und OFFSET noch fremd sind, da muss ich mal lesen und den Satz von BenderD muss ich auch erst mal Wort für Wort aufdröseln. Das mit dem Zurückblättern wollte ich genauso machen wie Fuerchau das beschreibt nur dann muss ich das komplette SQL absetzen ohne >= und beim Positionieren von einem Wert halt solange lesen bis ich dort bin. Ob ich das mit dem ScrollAble Cursor mache, weiß ich noch nicht, da habe ich wie bereits von Fuerchau erwähnt schlechte Erfahrung bei großer Datenmenge gemacht. Kann sein dass ich die Aktualisierung "händig" mittels CHAIN mache. Wobei ich dann halt auf die gelöschten Sätze und der Anzahl zurücklesender Sätze das selbst steuern muss. Ich schau mir jetzt mal alles an, was ihr geschrieben habt. Vielen Dank für Eure Zeit und Mühe.

Viele Grüße Harald

harkne
29-04-21, 12:59
Ich hab das verwechselt. SCROLLABLE mache ich ja. Aber werden da die Daten tatsächlich aktualisiert? Brauche ich da nicht ein SENSITIVE oder so?

BenderD
29-04-21, 13:02
und den Satz von BenderD muss ich auch erst mal Wort für Wort aufdröseln.
... out of my head:

PrepareStringUp = 'select * from myfile where Feld1 >= ? and Feld2 >= ? order by Feld3;
PrepareStringDown = 'select * from myfile where Feld1 < ? and Feld2 < ? order by Feld3 descending;

exec sql declare CUp cursor for SUp;
exec sql declare CDown cursor for SDown;

exec sql prepare SUp from PrepareStringUp;
exec sql prepare SDown from PrepareStringDown;

open CUp using :feld1, :feld2;

fetch Cup for 15 rows into :fetchrecDS;

close CUP;

analog rückwärts mit CDown.

Bei den zwei Vergleichsfeldern muss man aufpassen, ob die einfache Kopplung mit and, das ist, was man haben will oder ob das etwas komplizierter wird.

harkne
29-04-21, 14:29
@BenderD
So war auch ein gedanklicher Ansatzweg von mir, bei der Umsetzung hat es dann etwas gehapert, aber das hier sieht gut aus. Das gleich mit 2 Cursor zu machen ist natürlich auch gut. 2 Resultsets. Beim rückwärtsblättern im 1 Resultset und keine Daten mehr mit dem 2. Resultset weiter machen und umgekehrt.

Danke für die Hilfe. Tja wer die Wahl hat hat die Qual.

Ich hab mich jetzt erst mal für die andere Variante mit nur einem SQL und dann halt von Anfang an entschieden. Aber das kann je nach Aufwand sich noch ändern :-)

Fuerchau
29-04-21, 14:30
Stimmt, Sensitive ist für Aktualisierungen. Allerdings macht Scrollable ohne Sensitive wegen der Performance keinen Sinn, da sonst immer erst eine Kopie erstellt werden muss.

Was die Paginierung angeht, solltest du dich nicht um den Filter (Where) kümmern sondern nur um den Order By. Der Filter ist ja Users Wunsch und schränkt die Daten ein.
Einzig die dynamische Sortierung ist dein Problem bei der Subfileanzeige.

Neben Limit/Offset gibts noch eine Alternative in der Kombination mit D*B's Ansatz (wird auch öfters von Birgitta vorgeschlagen:

select * from (
select .....
,count(*) over () as Anzahl
,row_number() over (order by ....) Zeile
where UserFilter
) x
where Zeile between ? and ?
order by Zeile
fetch first n records

Die sog. Olap-Funktionen sind explizit für schnelle Ausführung entwickelt (einen Index über die Sortfelder sollte man trotzdem haben).
Du nummerierst die Zeilen entsprechend der gewünschten Sortierung.
Anschließend filterst du die gewünschten Zeile über deine Seitenlänge.
Der Sort nach Zeilennummer bringt dir die gewünschte Reihenfolge, da die Sortierung ja bereits erfolgt ist.

Vorteil: Du kannst auch nach Spalten sortieren, die nicht im Ergebnis leigen müssen.
Da die IBM i durchaus mehrere 10.000 Zeilen/Sekunde lesen kann, sollte die Performance kein Problem sein, und wer hat schon Lust, mehrere 100 Seiten durchzublättern.

Das Verfahren ist i.Ü. auch Sensitive, da ja ständig neu abgefragt wird.