DB2 Host Pagination

Status
Nicht offen für weitere Antworten.

byte

Top Contributor
Hallo,

kennt jemand eine Möglichkeit, wie man bei einer Host DB2 Pagination realisieren kann? Diese tolle Datenbank kennt weder SQL LIMIT noch ROW_NUMBER(). :mad:

Wäre über jeden Hinweis dankbar.

TIA byto
 

Ebenius

Top Contributor
Der erste Treffer bei Google "sql db2 limit" hilft Dir nicht? Sieht vielversprechend aus und soll angeblich gehen:
select * from
(SELECT Emp_No, First_Name, Last_Name, Deptt, ROW_NUMBER() OVER () AS RN
FROM EMP) AS col
where RN between 1 and 7;
Hast Du vielleicht die "OVER"-Klausel vergessen? Ich hab keine DB2, daher weiß ich nicht, ob's tut.

Ebenius
 

byte

Top Contributor
Wie gesagt, ROW_NUMBER() geht nicht. Hab jetzt rausgefunden, dass es ROW_NUMBER() für DB2 z/OS erst ab Version 9 gibt - unsere ist 8.2. :autsch:

Andere Ideen?
 

The_S

Top Contributor
Das hab ich mal gemacht, da gibts nen ähnlichen Befehl für. Hab heute nur blöderweise Urlaub und den Befehl nicht im Kopf. Wenn ichs nicht vergessen sollte, hast du vermutlich am Montag ne Antwort.
 

Ebenius

Top Contributor
Im Netz hab ich noch den "old-fashioned way" gefunden. :)
[HIGHLIGHT="SQL"]SELECT x.mycol1
FROM (
SELECT a.mycol1,
( SELECT COUNT(*) FROM mytable1 b WHERE b.mycol1 <= a.mycol1) AS rn
FROM mytable1 a
) x
WHERE x.rn BETWEEN 3 AND 5[/HIGHLIGHT]
Quelle: Free DB2 Forum (ganz unten).

Ebenius
 

robertpic71

Bekanntes Mitglied
Ich habe zwar DB2 nur auf der IBM iSeries, aber es sollte auch so gehen:

Code:
select * from aftpos where apfirma = 1 fetch first 20 rows only

Das ist zwar nur der LIMIT-Ersatz ohne Offset, aber notfalls kann mit ORDER BY Fachlicher eindeutiger Key + WHERE > letzter Fachlicher eindeutiger Key ein Paging basteln (die Greenscreen-Fraktion arbeitet praktisch nur so...)

Hier noch eine Variante von rownumer()

Code:
select * from                                            
 ( select rownumber() over() as rownum, aftpos.* from    
aftpos where apfirma = 1 ORDER BY APFIRMA, apaufnr       
) as inner where rownum between 25 and 50

Wie gesagt, ROW_NUMBER() geht nicht. Hab jetzt rausgefunden, dass es ROW_NUMBER() für DB2 z/OS erst ab Version 9 gibt - unsere ist 8.2.

Hast du du auch bei Schreibenweisen ROW_NUMBER() vs. ROWNUMER() probiert? Vielleicht ist ja nur eine neue Schreibweise mit V9 hinzugekommen. Auf der DB2/400 geht das schon seit einigen Versionen.

/Robert
 
Zuletzt bearbeitet:

byte

Top Contributor
Danke für eure nützlichen Tipps. FETCH FIRST X ROWS ONLY könnte ich als Notlösung benutzen, aber da ich einen Pageable JTable bauen will (max 100 Einträge pro Seite + Spaltensortierung durch die DB), wüsste ich nicht so genau, wie ich das damit realisieren könnte. Habe sowohl ROW_NUMBER() als auch ROWNUMBER() getestet. Funzt beides nicht. :noe:

@Ebenius - Danke. Diese Lösung hatte ich auch ergooglet und es funktioniert auch. Ich muss mal gucken, ob und wie ich da nun noch mein eigenes SELECT ... WHERE ... ORDER BY ... drin platzieren kann. Dann wär ich glücklich. :D

@maki - Danke. Leider nutzt diese Lösung auch wieder rownumber(). :bahnhof:
 

byte

Top Contributor
Im Netz hab ich noch den "old-fashioned way" gefunden. :)
[HIGHLIGHT="SQL"]SELECT x.mycol1
FROM (
SELECT a.mycol1,
( SELECT COUNT(*) FROM mytable1 b WHERE b.mycol1 <= a.mycol1) AS rn
FROM mytable1 a
) x
WHERE x.rn BETWEEN 3 AND 5[/HIGHLIGHT]
Quelle: Free DB2 Forum (ganz unten).

Ebenius

Es scheint echt zu funktionieren. Meine WHERE Kriterien bringe ich im WHERE vom COUNT(*) unter. Meine Sortierung kriege ich hin, indem ich beim <= meine Sortierspalte benutze und am Ende dann noch ein ORDER BY rn mache. Ich werds am Montag gleich mal auf der DB2 testen. :D
 

The_S

Top Contributor
Hat sich ja scheinbar erledigt. Hab das damals auch mit FETCH FIRST X ROWS ONLY gemacht (nur zur Vervollständigung).
 

byte

Top Contributor
Hab das Statement von oben nun mal mit intensiver auf der DB2 getestet und es ist grottenlangsam bei großen Datenmengen bzw. verursacht sogar ein Timeout bei sehr großen Datenmengen. Ist also auch nicht die Lösung.

Hat sich ja scheinbar erledigt. Hab das damals auch mit FETCH FIRST X ROWS ONLY gemacht (nur zur Vervollständigung).

Wie hast Du das denn genau gemacht?
 

The_S

Top Contributor
In Kombination mit ROW_NUMBER - sorry, total vergessen, dass wir letztens auf die V9 umgestellt haben :eek:
 

byte

Top Contributor
Hab mir jetzt mal Gedanken drüber gemacht. Grundsätzlich würde es auch mit FETCH FIRST X ROWS ONLY alleine gehen, wenn ich mir jeweils den letzten Wert der Sortierungsspalte merke. Dann wäre die nächste Seite SELECT ... WHERE sort_column > last_value FETCH FIRST 100 ROWS ONLY. Man könnte dann zwar nicht eine gezielte Seite anspringen, sondern müsste sich imemr durchklicken, aber das wäre wohl zu verkraften.
 

robertpic71

Bekanntes Mitglied
... wenn ich mir jeweils den letzten Wert der Sortierungsspalte merke. Dann wäre die nächste Seite SELECT ... WHERE sort_column > last_value FETCH FIRST 100 ROWS ONLY. Man könnte dann zwar nicht eine gezielte Seite anspringen, sondern müsste sich imemr durchklicken, aber das wäre wohl zu verkraften.

Zu berücksichtigen ist noch das die Sortbegriff eindeutig sein müssen. Notfalls noch etwas daran hängen (eindeutiger fachlicher Schlüssel oder die ID).

Beispiel:
select * from rechnungen order by redatum

Seite 1:
Datum Re-Nr
...
12.12.08 #4001
20.12.08 #4002
31.12.08 #4003
31.12.08 #4004
31.12.08 #4005

Seite 2:
31.12.08 #4006
31.12.08 #4007
04.01.09 #5000
...
Bei nicht eindeutigen Schlüsseln geht in solchen Situationen etwas daneben.

Also besser: ... order by redatum, renr
und where ((redatum > :ledatum) or (redatum = :ledatum and renr > :lernr))

le... letzte Satz

Zusatzfrage: Machst du vorher ein COUNT(*)?
Wg. Seite=100, 400=Einträge der letzte Eintrag liefert kein eof, man bietet noch eine Seite an, welche dann leer ist.
Abhilfe: count(*) oder nach der Verarbeitungsschleife noch resultSet.next() zur Ermittlung des Endeflags.

/Robert
 

byte

Top Contributor
Danke für den Hinweis mit der Eindeutigkeit. Würds dann genauso machen, also auf Sortierspalte + PrimaryKey gehen, um die Eindeutigkeit zu gewährleisten.

Bzgl. der Zusatzfrage: Ja, würde dann COUNT(*) machen, um die maximale Anzahl Elemente anzuzeigen. Daraus ergibt sich dann:

COUNT(*) % Pagesize = Max. Anzahl Seiten

Der JTable hätte dann Knöpfe für Vor und Zurück und aktuelle Seite / max. Anzahl Seiten und max. Anzahl Elemente anzeigen.

Am liebsten wärs mit natürlich, wenn man auch gezielt Seiten oder direkt ans Ende springen könnte, aber das geht dann halt nicht auf der alten DB2.
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Oben