Wie kann ich die Anzahl der von einer Oracle-Abfrage nach der Bestellung zurückgegebenen Zeilen begrenzen?

1032

Gibt es eine Möglichkeit, eine OracleAbfrage so zu verhalten, als ob sie eine MySQL limitKlausel enthält ?

In MySQLkann ich das tun:

select * 
from sometable
order by name
limit 20,10

Um die 21. bis 30. Reihe zu erhalten (überspringen Sie die ersten 20, geben Sie die nächsten 10 an). Die Zeilen werden nach dem ausgewählt order by, so dass es wirklich mit dem 20. Namen alphabetisch beginnt.

In Oracle, das einzige , was Leute erwähnen ist die rownumPseudo-Spalte, aber es wird ausgewertet , bevor order by , was bedeutet dies:

select * 
from sometable
where rownum <= 10
order by name

gibt einen zufälligen Satz von zehn nach Namen geordneten Zeilen zurück, was normalerweise nicht das ist, was ich will. Es ist auch nicht möglich, einen Versatz anzugeben.

Mathieu Longtin
quelle
16
Standardisiert in SQL: 2008.
dalle
14
Limit wurde von Tom Kyte für Oracle 12c ...
Wolφi
14
Die nächste Seite in einer Ergebnismenge abrufen?
Mathieu Longtin
3
@YaroslavShabalin Insbesondere bei einer ausgelagerten Suche wird dieses Muster ständig verwendet . Fast jede App mit einer Suchfunktion wird sie verwenden. Ein anderer Anwendungsfall wäre, nur einen Teil einer langen Liste oder Tabelle clientseitig zu laden und dem Benutzer die Option zum Erweitern zu geben.
jpmc26
3
@YaroslavShabalin Sie können keine andere Ergebnismenge erhalten, es sei denn, die zugrunde liegenden Daten ändern sich aufgrund der ORDER BY. Das ist der springende Punkt bei der Bestellung. Wenn sich die zugrunde liegenden Daten ändern und sich Ihre Ergebnismenge aufgrund dessen ändert, zeigen Sie dem Benutzer dann die aktualisierten Ergebnisse anstelle veralteter Informationen an. Auch das Staatsmanagement ist eine Plage, die so weit wie möglich vermieden werden sollte. Es ist eine ständige Quelle von Komplikationen und Fehlern. Deshalb wird funktional immer beliebter. Und wann würden Sie wissen, dass die gesamte Ergebnismenge im Speicher abläuft? Im Web können Sie nicht wissen, wann der Benutzer das Web verlässt.
jpmc26

Antworten:

621

Ab Oracle 12c R1 (12.1) gibt es eine Zeilenbegrenzungsklausel . Es verwendet keine vertraute LIMITSyntax, kann aber mit mehr Optionen die Arbeit besser erledigen. Die vollständige Syntax finden Sie hier . (Lesen Sie in dieser Antwort auch mehr darüber, wie dies intern in Oracle funktioniert .)

Um die ursprüngliche Frage zu beantworten, ist hier die Abfrage:

SELECT * 
FROM   sometable
ORDER BY name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

(Informationen zu früheren Oracle-Versionen finden Sie in anderen Antworten in dieser Frage.)


Beispiele:

Die folgenden Beispiele wurden von der verlinkten Seite zitiert , in der Hoffnung, Linkfäule zu verhindern.

Installieren

CREATE TABLE rownum_order_test (
  val  NUMBER
);

INSERT ALL
  INTO rownum_order_test
SELECT level
FROM   dual
CONNECT BY level <= 10;

COMMIT;

Was ist in der Tabelle?

SELECT val
FROM   rownum_order_test
ORDER BY val;

       VAL
----------
         1
         1
         2
         2
         3
         3
         4
         4
         5
         5
         6
         6
         7
         7
         8
         8
         9
         9
        10
        10

20 rows selected.

Holen Sie sich die ersten NZeilen

SELECT val
FROM   rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS ONLY;

       VAL
----------
        10
        10
         9
         9
         8

5 rows selected.

Holen ersten NReihen, wenn Nth Reihe Bindungen hat, erhalten alle gebunden Reihen

SELECT val
FROM   rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS WITH TIES;

       VAL
----------
        10
        10
         9
         9
         8
         8

6 rows selected.

Top x% der Zeilen

SELECT val
FROM   rownum_order_test
ORDER BY val
FETCH FIRST 20 PERCENT ROWS ONLY;

       VAL
----------
         1
         1
         2
         2

4 rows selected.

Verwendung eines Versatzes, sehr nützlich für die Paginierung

SELECT val
FROM   rownum_order_test
ORDER BY val
OFFSET 4 ROWS FETCH NEXT 4 ROWS ONLY;

       VAL
----------
         3
         3
         4
         4

4 rows selected.

Sie können Offset mit Prozentsätzen kombinieren

SELECT val
FROM   rownum_order_test
ORDER BY val
OFFSET 4 ROWS FETCH NEXT 20 PERCENT ROWS ONLY;

       VAL
----------
         3
         3
         4
         4

4 rows selected.
Sampathsris
quelle
1
Nur um es zu erweitern: OFFSET FETCHSyntax ist eine Syntax Zucker. Details
Lukasz Szozda
793

Sie können hierfür eine Unterabfrage verwenden

select *
from  
( select * 
  from emp 
  order by sal desc ) 
where ROWNUM <= 5;

Weitere Informationen finden Sie auch im Thema Zu ROWNUM und zur Einschränkung der Ergebnisse bei Oracle / AskTom.

Update : Um das Ergebnis sowohl auf die Unter- als auch auf die Obergrenze zu beschränken, werden die Dinge etwas aufgeblähter

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;

(Aus dem angegebenen AskTom-Artikel kopiert)

Update 2 : Ab Oracle 12c (12.1) steht eine Syntax zur Verfügung, mit der Zeilen begrenzt oder bei Offsets begonnen werden können.

SELECT * 
FROM   sometable
ORDER BY name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

Weitere Beispiele finden Sie in dieser Antwort . Danke an Krumia für den Hinweis.

Kosi2801
quelle
5
Dies ist definitiv der richtige Weg, aber beachten Sie (wie im Artikel von ask tom angegeben), dass sich die Abfrageleistung mit zunehmendem Rownum verschlechtert. Dies ist eine gute Lösung für Abfrageergebnisse, bei denen nur die ersten Seiten angezeigt werden sollen. Wenn Sie dies jedoch als Mechanismus verwenden, mit dem Code eine ganze Tabelle durchblättert, sollten Sie Ihren Code besser umgestalten
Chris Gill
1
+1 Ihre untere / obere Version hat mir tatsächlich dabei geholfen, ein Problem zu umgehen, bei dem eine bloße Rownum-Klausel mit oberer Grenze meine Abfrage drastisch verlangsamte.
Kelvin
1
Die "analytische Lösung von Leigh Riffel mit nur einer verschachtelten Abfrage" ist diejenige.
Darren Hicks
7
Der AskTom-Artikel enthält auch einen Optimierungshinweis, der SELECT / * + FIRST_ROWS (n) / a verwendet. , rownum rnum Vor dem schließenden Schrägstrich sollte ein Sternchen stehen. SO schrubbt es aus.
David Mann
1
Beachten Sie, dass für Oracle 11 ein äußeres SELECT mit ROWNUM verhindert, dass Sie deleteRow in einem UpdatableResultSet (mit ORA-01446) aufrufen - wir freuen uns auf diese 12c R1-Änderung!
Nsandersen
185

Ich habe einige Leistungstests für die folgenden Ansätze durchgeführt:

Asktom

select * from (
  select a.*, ROWNUM rnum from (
    <select statement with order by clause>
  ) a where rownum <= MAX_ROW
) where rnum >= MIN_ROW

Analytisch

select * from (
  <select statement with order by clause>
) where myrow between MIN_ROW and MAX_ROW

Kurze Alternative

select * from (
  select statement, rownum as RN with order by clause
) where a.rn >= MIN_ROW and a.rn <= MAX_ROW

Ergebnisse

Die Tabelle hatte 10 Millionen Datensätze. Die Sortierung erfolgte in einer nicht indizierten Datums- / Uhrzeitzeile:

  • Der Erklärungsplan zeigte für alle drei Auswahlen den gleichen Wert (323168).
  • Aber der Gewinner ist AskTom (gefolgt von der Analyse)

Die Auswahl der ersten 10 Zeilen dauerte:

  • AskTom: 28-30 Sekunden
  • Analytisch: 33-37 Sekunden
  • Kurze Alternative: 110-140 Sekunden

Zeilen zwischen 100.000 und 100.010 auswählen:

  • AskTom: 60 Sekunden
  • Analytisch: 100 Sekunden

Zeilen zwischen 9.000.000 und 9.000.010 auswählen:

  • AskTom: 130 Sekunden
  • Analytisch: 150 Sekunden
Zeldi
quelle
Gute Arbeit. Haben Sie die kurze Alternative mit einem Zwischen anstelle von> = und <= ausprobiert?
Mathieu Longtin
4
@ MathieuLongtin BETWEENist nur eine Abkürzung für >= AND <=( stackoverflow.com/questions/4809083/between-clause-versus-and )
wweicker
1
zeldi - Auf welcher Version war das? Oracle hat die analytische Leistung in 11.1 verbessert. und 11.2.
Leigh Riffel
@Leigh Riffel Es war 10.2.0.5; Eines Tages könnte ich mir Zeit nehmen und auch die 11i-Version überprüfen.
Zeldi
5
Ich habe einige schnelle Tests durchgeführt und ähnliche Ergebnisse für 12c erhalten. Die neue offsetSyntax hat den gleichen Plan und die gleiche Leistung wie der analytische Ansatz.
Jon Heller
55

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;

Rank()könnte ersetzt werden Row_Number(), könnte aber mehr Datensätze zurückgeben, als Sie erwarten, wenn es doppelte Werte für den Namen gibt.

Leigh Riffel
quelle
3
Ich liebe Analytik. Vielleicht möchten Sie den Unterschied im Verhalten zwischen Rank () und Row_Number () klären.
Dave Costa
Ich bin mir nicht sicher, warum ich nicht an Duplikate gedacht habe. Wenn in diesem Fall doppelte Werte für den Namen vorhanden sind, kann RANK mehr Datensätze liefern, als Sie erwarten. Daher sollten Sie Row_Number verwenden.
Leigh Riffel
Wenn erwähnt wird rank(), ist es auch erwähnenswert, dense_rank()was für die Ausgabesteuerung nützlicher sein kann, da letztere keine Zahlen "überspringt", wohingegen dies möglich rank()ist. In jedem Fall ist diese Frage row_number()am besten geeignet. Eine andere nicht ist, dass diese Technik auf jede Datenbank anwendbar ist, die die genannten Funktionen unterstützt.
Used_By_Already
28

Unter Oracle 12c (siehe Zeilenbegrenzungsklausel in der SQL-Referenz ):

SELECT * 
FROM sometable
ORDER BY name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
beldaz
quelle
53
Und natürlich mussten sie eine völlig andere Syntax verwenden als alle anderen bisher
Mathieu Longtin
9
Nachdem sie sich mit allen anderen Anbietern zusammengesetzt hatten, um sich auf LIMITSQL: 2008 zu einigen, mussten sie natürlich ein Blatt aus Microsofts Buch herausnehmen und den Standard brechen.
Beldaz
1
Interessanterweise habe ich kürzlich gehört, dass der neueste Standard diese Syntax enthält. Vielleicht hat Oracle sie vor der Implementierung zuerst eingeführt. Wahrscheinlich ist es flexibler alsLIMIT ... OFFSET
beldaz
3
@Derek: Ja, es ist bedauerlich, nicht dem Standard zu folgen. Die neu eingeführte Funktionalität in 12cR1 ist jedoch leistungsfähiger als nur LIMIT n, m(siehe meine Antwort). Andererseits sollte Oracle LIMIT n, mals syntaktischen Zucker implementiert haben , wie es äquivalent zu ist OFFSET n ROWS FETCH NEXT m ROWS ONLY.
Sampathsris
10
@Derek: Eigentlich habe ich diese Bemerkung gerade im PostgreSQL-Handbuch postgresql.org/docs/9.0/static/sql-select.html#AEN69535 bemerkt. "Die Klauseln LIMIT und OFFSET sind PostgreSQL-spezifische Syntax, die auch von MySQL verwendet wird. The SQL : Der Standard von 2008 hat die Klauseln OFFSET ... FETCH {FIRST | NEXT} ... für dieselbe Funktionalität eingeführt. " LIMIT war also nie Teil des Standards.
beldaz
14

Paginierungsabfragen bei der Bestellung sind in Oracle sehr schwierig.

Oracle stellt eine ROWNUM-Pseudospalte bereit, die eine Zahl zurückgibt, die die Reihenfolge angibt, in der die Datenbank die Zeile aus einer Tabelle oder einem Satz verbundener Ansichten auswählt.

ROWNUM ist eine Pseudospalte, die viele Menschen in Schwierigkeiten bringt. Ein ROWNUM-Wert wird einer Zeile nicht dauerhaft zugewiesen (dies ist ein häufiges Missverständnis). Es kann verwirrend sein, wenn tatsächlich ein ROWNUM-Wert zugewiesen wird. Ein ROWNUM-Wert wird einer Zeile zugewiesen, nachdem Filterfilterprädikate der Abfrage übergeben wurden, jedoch bevor die Abfrage aggregiert oder sortiert wird .

Darüber hinaus wird ein ROWNUM-Wert erst nach seiner Zuweisung erhöht.

Aus diesem Grund gibt die folgende Abfrage keine Zeilen zurück:

 select * 
 from (select *
       from some_table
       order by some_column)
 where ROWNUM <= 4 and ROWNUM > 1; 

Die erste Zeile des Abfrageergebnisses übergibt nicht das Prädikat ROWNUM> 1, sodass ROWNUM nicht auf 2 erhöht wird. Aus diesem Grund wird kein ROWNUM-Wert größer als 1, sodass die Abfrage keine Zeilen zurückgibt.

Eine korrekt definierte Abfrage sollte folgendermaßen aussehen:

select *
from (select *, ROWNUM rnum
      from (select *
            from skijump_results
            order by points)
      where ROWNUM <= 4)
where rnum > 1; 

Weitere Informationen zu Paginierungsabfragen finden Sie in meinen Artikeln im Vertabelo- Blog:

Bartek
quelle
2
Die erste Zeile des Abfrageergebnisses besteht nicht das Prädikat ROWNUM> 1 (…) - eine positive Bewertung, um dies zu erklären.
Piotr Dobrogost
6

SQL Standard

Wie in diesem Artikel erläutert , bietet der SQL: 2008-Standard die folgende Syntax, um die SQL-Ergebnismenge einzuschränken:

SELECT
    title
FROM
    post
ORDER BY
    id DESC
FETCH FIRST 50 ROWS ONLY

Oracle 11g und ältere Versionen

Vor Version 12c mussten Sie zum Abrufen der Top-N-Datensätze eine abgeleitete Tabelle und die Pseudospalte ROWNUM verwenden:

SELECT *
FROM (
    SELECT
        title
    FROM
        post
    ORDER BY
        id DESC
)
WHERE ROWNUM <= 50
Vlad Mihalcea
quelle
5

Weniger SELECT-Anweisungen. Auch weniger leistungsaufwendig. Credits an: [email protected]

SELECT *
    FROM   (SELECT t.*,
                   rownum AS rn
            FROM   shhospede t) a
    WHERE  a.rn >= in_first
    AND    a.rn <= in_first;
Felipe Q. Giovanoni
quelle
2
Darüber hinaus ist es völlig falsche Antwort. Die Frage betraf die Begrenzung NACH dem Sortieren. Rownum sollte also keine Unterabfrage mehr haben.
BitLord
5

Als Erweiterung der akzeptierten Antwort verwendet Oracle intern ROW_NUMBER/RANKFunktionen. OFFSET FETCHSyntax ist eine Syntax Zucker.

Es konnte unter Verwendung des folgenden DBMS_UTILITY.EXPAND_SQL_TEXTVerfahrens beobachtet werden :

Probe vorbereiten:

CREATE TABLE rownum_order_test (
  val  NUMBER
);

INSERT ALL
  INTO rownum_order_test
SELECT level
FROM   dual
CONNECT BY level <= 10;
COMMIT;

Abfrage:

SELECT val
FROM   rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS ONLY;

ist regelmäßig:

SELECT "A1"."VAL" "VAL" 
FROM  (SELECT "A2"."VAL" "VAL","A2"."VAL" "rowlimit_$_0",
               ROW_NUMBER() OVER ( ORDER BY "A2"."VAL" DESC ) "rowlimit_$$_rownumber" 
      FROM "ROWNUM_ORDER_TEST" "A2") "A1" 
WHERE "A1"."rowlimit_$$_rownumber"<=5 ORDER BY "A1"."rowlimit_$_0" DESC;

db <> Geigen-Demo

Abrufen von erweitertem SQL-Text:

declare
  x VARCHAR2(1000);
begin
 dbms_utility.expand_sql_text(
        input_sql_text => '
          SELECT val
          FROM   rownum_order_test
          ORDER BY val DESC
          FETCH FIRST 5 ROWS ONLY',
        output_sql_text => x);

  dbms_output.put_line(x);
end;
/

WITH TIESwird erweitert als RANK:

declare
  x VARCHAR2(1000);
begin
 dbms_utility.expand_sql_text(
        input_sql_text => '
          SELECT val
          FROM   rownum_order_test
          ORDER BY val DESC
          FETCH FIRST 5 ROWS WITH TIES',
        output_sql_text => x);

  dbms_output.put_line(x);
end;
/

SELECT "A1"."VAL" "VAL" 
FROM  (SELECT "A2"."VAL" "VAL","A2"."VAL" "rowlimit_$_0",
              RANK() OVER ( ORDER BY "A2"."VAL" DESC ) "rowlimit_$$_rank" 
       FROM "ROWNUM_ORDER_TEST" "A2") "A1" 
WHERE "A1"."rowlimit_$$_rank"<=5 ORDER BY "A1"."rowlimit_$_0" DESC

und Offset:

declare
  x VARCHAR2(1000);
begin
 dbms_utility.expand_sql_text(
        input_sql_text => '
          SELECT val
FROM   rownum_order_test
ORDER BY val
OFFSET 4 ROWS FETCH NEXT 4 ROWS ONLY',
        output_sql_text => x);

  dbms_output.put_line(x);
end;
/


SELECT "A1"."VAL" "VAL" 
FROM  (SELECT "A2"."VAL" "VAL","A2"."VAL" "rowlimit_$_0",
             ROW_NUMBER() OVER ( ORDER BY "A2"."VAL") "rowlimit_$$_rownumber" 
       FROM "ROWNUM_ORDER_TEST" "A2") "A1" 
       WHERE "A1"."rowlimit_$$_rownumber"<=CASE  WHEN (4>=0) THEN FLOOR(TO_NUMBER(4)) 
             ELSE 0 END +4 AND "A1"."rowlimit_$$_rownumber">4 
ORDER BY "A1"."rowlimit_$_0"
Lukasz Szozda
quelle
3

Wenn Sie nicht mit Oracle 12C arbeiten, können Sie die TOP N-Abfrage wie folgt verwenden.

SELECT *
 FROM
   ( SELECT rownum rnum
          , a.*
       FROM sometable a 
   ORDER BY name
   )
WHERE rnum BETWEEN 10 AND 20;

Sie können dies sogar wie folgt aus der Klausel in die Klausel verschieben

WITH b AS
( SELECT rownum rnum
      , a.* 
   FROM sometable a ORDER BY name
) 
SELECT * FROM b 
WHERE rnum BETWEEN 10 AND 20;

Hier erstellen wir tatsächlich eine Inline-Ansicht und benennen rownum in rnum um. Sie können rnum in der Hauptabfrage als Filterkriterium verwenden.

Sandi
quelle
1
In meinem Fall hat dies nicht die richtigen Zeilen zurückgegeben. Was ich getan habe, um das Problem zu beheben, ist, das ORDER BYund das rownumseparat zu tun . Grundsätzlich habe ich eine Unterabfrage erstellt, die die ORDER BYKlausel hatte .
Patrick Gregorio
Downvote als falsche Antwort. Die Frage rownumbetraf die Begrenzung nach dem Sortieren, sollte also außerhalb einer Unterabfrage liegen.
Piotr Dobrogost
@PiotrDobrogost Rownum ist nur draußen.
Sandi
2

Ich habe begonnen, mich auf die Oracle 1z0-047-Prüfung vorzubereiten, die gegen 12c validiert wurde. Als ich mich darauf vorbereitete, stieß ich auf eine 12c-Verbesserung, die als "FETCH FIRST" bekannt ist. Sie ermöglicht es Ihnen, Zeilen nach Belieben abzurufen / zu begrenzen. Damit stehen mehrere Optionen zur Verfügung

- FETCH FIRST n ROWS ONLY
 - OFFSET n ROWS FETCH NEXT N1 ROWS ONLY // leave the n rows and display next N1 rows
 - n % rows via FETCH FIRST N PERCENT ROWS ONLY

Beispiel:

Select * from XYZ a
order by a.pqr
FETCH FIRST 10 ROWS ONLY
Arjun Gaur
quelle
3
stackoverflow.com/a/26051830/635608 - dies wurde bereits in anderen Antworten angegeben. Bitte veröffentlichen Sie keine Inhalte, die bereits vor Monaten veröffentlicht wurden.
Mat
1
Oh sicher, habe nicht jede Antwort durchgesehen, ich bin schon früh auf die Unterabfrage gestoßen, werde das im Hinterkopf behalten.
Arjun Gaur
1
select * FROM (SELECT 
   ROW_NUMBER() OVER (ORDER BY sal desc),* AS ROWID, 
 FROM EMP ) EMP  where ROWID=5

größer als Werte herausfinden

select * FROM (SELECT 
       ROW_NUMBER() OVER (ORDER BY sal desc),* AS ROWID, 
     FROM EMP ) EMP  where ROWID>5

weniger als Werte herausfinden

select * FROM (SELECT 
       ROW_NUMBER() OVER (ORDER BY sal desc),* AS ROWID, 
     FROM EMP ) EMP  where ROWID=5
Mehul Akabari
quelle
Downvote als ROW_NUMBER()basierte Lösung wurde bereits von Leigh Riffel veröffentlicht. In der Sucht werden Syntaxfehler im angezeigten Code angezeigt.
Piotr Dobrogost
1

Für jede von einer Abfrage zurückgegebene Zeile gibt die Pseudospalte ROWNUM eine Zahl zurück, die die Reihenfolge angibt, in der Oracle die Zeile aus einer Tabelle oder einem Satz verbundener Zeilen auswählt. Die erste ausgewählte Zeile hat eine ROWNUM von 1, die zweite hat 2 und so weiter.

  SELECT * FROM sometable1 so
    WHERE so.id IN (
    SELECT so2.id from sometable2 so2
    WHERE ROWNUM <=5
    )
    AND ORDER BY so.somefield AND ROWNUM <= 100 

Ich habe dies in oracleServer implementiert11.2.0.1.0

Sumesh TG
quelle
Abstimmen, da die Frage nach der Begrenzung der geordneten Zeilen fragt und Sie nicht einmal Ordnung haben
Piotr Dobrogost
@PiotrDobrogost Verstehe, dass dies keine große Aufgabe ist. Das Bestellen von Schlüsselwörtern ist für alle rdbms gleich. Nur das Limit hat Änderungen.
Sumesh TG
-1

Bei SQL-Developer werden automatisch nur die ersten 50 Zeilen abgerufen. Und wenn wir nach unten scrollen, werden weitere 50 Zeilen abgerufen und so weiter!

Daher müssen wir im Falle eines SQL-Entwickler-Tools nicht definieren!

Aditya Goel
quelle
-3

Im Orakel

SELECT val FROM   rownum_order_test ORDER BY val DESC FETCH FIRST 5 ROWS ONLY;

VAL

    10
    10
     9
     9
     8

5 Zeilen ausgewählt.

SQL>

Rakesh
quelle
7
Sie sollten angeben, dass dies ab Oracle 12c gilt und dass Sie dies von irgendwoher kopieren / einfügen - bitte geben Sie immer Ihre Quellen an.
Mat
Die Quelle ist diese @Mat. Und Rakesh, bitte versuchen Sie zumindest, die Antwort für die ursprüngliche Frage anzupassen. Ich habe auch eine Antwort gegeben, die dieselbe Quelle zitiert, aber ich habe versucht, umfassend zu sein und die ursprüngliche Quelle zitiert.
Sampathsris
-4

(ungetestet) so etwas kann den Job machen

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 den Rang der Analysefunktion, nach dem Sie bestellen können.

EvilTeach
quelle
2
Dies gibt keine einzelne Zeile zurück, da ROWNUM eine Spalte in der Ergebnismenge ist, sodass die letzte WHERE-Bedingung immer falsch ist. Außerdem können Sie ROWNUM und eine ORDER BY-Garantie nicht verwenden.
Ben
2
Ausgezeichnet. Lassen wir dies hier als Warnung für andere.
EvilTeach
-5

Gleich wie oben mit Korrekturen. Funktioniert aber definitiv nicht schön.

   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

Ehrlich gesagt, besser, die obigen Antworten zu verwenden.

stimepy
quelle
5
Dies ist falsch, da die WHERE-Klausel vor ORDER BY ausgewertet wird.
Ben
3
Interessanterweise gestohlen von meiner schlechten Antwort unten.
EvilTeach