Gibt es eine Möglichkeit, eine Oracle-Abfrage so zu gestalten, dass sie eine MySQL-Limit-Klausel enthält?
In MySQL
kann ich das tun:
select *
from sometable
order by name
limit 20,10
um die 21. bis 30. Zeile zu erhalten (die ersten 20 werden übersprungen, die nächsten 10 werden ausgegeben). Die Zeilen werden nach dem Ordnen nach
ausgewählt, so dass es wirklich mit dem 20.
In Oracle
wird nur die Pseudospalte rownum
erwähnt, aber sie wird vor order by
ausgewertet, was dies bedeutet:
select *
from sometable
where rownum <= 10
order by name
wird eine zufällige Menge von zehn Zeilen zurückgeben, die nach Namen geordnet sind, was normalerweise nicht das ist, was ich will. Außerdem ist es nicht möglich, einen Offset anzugeben.
Sie können dafür eine Unterabfrage verwenden wie
select *
from
( select *
from emp
order by sal desc )
where ROWNUM <= 5;
Weitere Informationen finden Sie auch unter dem Thema On ROWNUM and limiting results bei Oracle/AskTom.
Update: Um das Ergebnis sowohl nach unten als auch nach oben zu begrenzen, wird die Sache etwas aufgebläht mit
select * from
( select a.*, ROWNUM rnum from
( <your_query_goes_here, with order by> ) a
where ROWNUM <= :MAX_ROW_TO_FETCH )
where rnum >= :MIN_ROW_TO_FETCH;
(Kopiert aus dem angegebenen AskTom-Artikel)
Update 2: Ab Oracle 12c (12.1) gibt es eine Syntax, um Zeilen zu begrenzen oder mit Offsets zu beginnen.
SELECT *
FROM sometable
ORDER BY name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
Siehe diese Antwort für weitere Beispiele. Vielen Dank an Krumia für den Hinweis.
Eine analytische Lösung mit nur einer verschachtelten Abfrage:
SELECT * FROM
(
SELECT t.*, Row_Number() OVER (ORDER BY name) MyRow FROM sometable t
)
WHERE MyRow BETWEEN 10 AND 20;
Rang()" könnte durch "Zeilennummer()" ersetzt werden, gibt aber möglicherweise mehr Datensätze zurück, als Sie erwarten, wenn es doppelte Werte für Name gibt.
(ungetestet) etwas wie dieses könnte die Aufgabe erfüllen
WITH
base AS
(
select * -- get the table
from sometable
order by name -- in the desired order
),
twenty AS
(
select * -- get the first 30 rows
from base
where rownum < 30
order by name -- in the desired order
)
select * -- then get rows 21 .. 30
from twenty
where rownum > 20
order by name -- in the desired order
Es gibt auch die analytische Funktion rank, die man zum Ordnen nach verwenden kann.