Bagaimana cara membatasi jumlah baris yang dikembalikan oleh permintaan Oracle setelah memesan?

1032

Apakah ada cara untuk membuat Oraclekueri berperilaku seperti mengandung MySQL limitklausa?

Dalam MySQL, saya bisa melakukan ini:

select * 
from sometable
order by name
limit 20,10

untuk mendapatkan baris ke-21 hingga ke-30 (lewati 20 pertama, berikan 10 berikutnya). Baris dipilih setelah order by, jadi itu benar-benar dimulai pada nama ke-20 secara abjad.

Dalam Oracle, satu-satunya hal yang orang sebutkan adalah rownumpseudo-kolom, tetapi dievaluasi sebelumnya order by , yang artinya:

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

akan mengembalikan satu set acak sepuluh baris yang dipesan dengan nama, yang biasanya tidak saya inginkan. Itu juga tidak memungkinkan untuk menentukan offset.

Mathieu Longtin
sumber
16
Standar dalam SQL: 2008.
dalle
14
Limit diumumkan oleh Tom Kyte untuk Oracle 12c ...
wolφi
14
Mengambil halaman berikutnya dalam set hasil?
Mathieu Longtin
3
@YaroslavShabalin Secara khusus, pencarian halaman menggunakan pola ini sepanjang waktu. Hampir semua aplikasi dengan fungsi pencarian apa pun akan menggunakannya. Kasus penggunaan lain hanya akan memuat bagian dari daftar panjang atau sisi klien dan memberi pengguna opsi untuk memperluas.
jpmc26
3
@YaroslavShabalin Anda tidak bisa mendapatkan set hasil yang berbeda kecuali data yang mendasarinya berubah karena ORDER BY. Itulah inti dari pemesanan terlebih dahulu. Jika data yang mendasarinya berubah dan hasil Anda menyetel perubahan karenanya, mengapa tidak menunjukkan kepada pengguna hasil yang diperbarui alih-alih informasi yang ketinggalan zaman? Juga, manajemen negara adalah wabah yang harus dihindari sebanyak mungkin. Ini merupakan sumber komplikasi dan bug yang konstan; itu sebabnya fungsional menjadi sangat populer. Dan kapan Anda tahu akan berakhir seluruh hasil yang diatur dalam memori? Di web, Anda tidak memiliki cara untuk mengetahui kapan pengguna pergi.
jpmc26

Jawaban:

621

Mulai dari Oracle 12c R1 (12,1), ada adalah sebuah baris membatasi klausa . Itu tidak menggunakan LIMITsintaks akrab , tetapi dapat melakukan pekerjaan dengan lebih baik dengan lebih banyak opsi. Anda dapat menemukan sintaksis lengkap di sini . (Baca juga lebih lanjut tentang bagaimana ini bekerja secara internal di Oracle dalam jawaban ini ).

Untuk menjawab pertanyaan awal, inilah pertanyaannya:

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

(Untuk versi Oracle sebelumnya, silakan merujuk ke jawaban lain dalam pertanyaan ini)


Contoh:

Contoh-contoh berikut dikutip dari halaman tertaut , dengan harapan mencegah pembusukan tautan.

Mendirikan

CREATE TABLE rownum_order_test (
  val  NUMBER
);

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

COMMIT;

Apa yang ada di meja?

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.

Dapatkan Nbaris pertama

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

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

5 rows selected.

Dapatkan Nbaris pertama , jika baris Nth memiliki ikatan, dapatkan semua baris terikat

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.

x% Atas baris

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

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

4 rows selected.

Menggunakan offset, sangat berguna untuk pagination

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.

Anda dapat menggabungkan offset dengan persentase

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
sumber
1
Hanya untuk memperpanjang: OFFSET FETCHsintaks adalah gula sintaks. Detail
Lukasz Szozda
793

Anda dapat menggunakan subquery untuk seperti ini

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

Lihat juga pada topik Pada ROWNUM dan batasi hasil di Oracle / AskTom untuk informasi lebih lanjut.

Pembaruan : Untuk membatasi hasil dengan batas bawah dan atas hal-hal menjadi sedikit lebih membengkak

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;

(Disalin dari artikel AskTom yang ditentukan)

Pembaruan 2 : Dimulai dengan Oracle 12c (12.1) ada sintaks yang tersedia untuk membatasi baris atau mulai dari offset.

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

Lihat jawaban ini untuk lebih banyak contoh. Terima kasih kepada Krumia untuk petunjuknya.

Kosi2801
sumber
5
Ini jelas merupakan cara untuk melakukannya, tetapi berhati-hatilah (seperti yang diminta artikel tom) kinerja query menurun ketika max rownum Anda meningkat. Ini adalah solusi yang bagus untuk hasil kueri di mana Anda hanya ingin melihat beberapa halaman pertama, tetapi jika Anda menggunakan ini sebagai mekanisme untuk kode untuk halaman melalui seluruh tabel Anda akan lebih baik refactoring kode Anda
Chris Gill
1
+1 versi bawah / atas Anda benar-benar membantu saya mengatasi masalah di mana klausa rownum hanya dibatasi secara drastis memperlambat kueri saya.
Kelvin
1
"Solusi analitik Leigh Riffel dengan hanya satu kueri tersarang" adalah solusinya.
Darren Hicks
7
Artikel AskTom juga memiliki petunjuk pengoptimal yang menggunakan SELECT / * + FIRST_ROWS (n) / a. , rownum rnum Slash penutup harus didahului dengan tanda bintang. SO sedang menggosoknya.
David Mann
1
Perhatikan bahwa untuk Oracle 11 SELECT luar dengan ROWNUM akan mencegah Anda memanggil deleteRow di UpdatableResultSet (dengan ORA-01446) - menantikan perubahan 12c R1!
nsandersen
185

Saya melakukan beberapa pengujian kinerja untuk pendekatan berikut:

Asktom

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

Analitik

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

Alternatif Singkat

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

Hasil

Tabel memiliki 10 juta catatan, mengurutkan pada baris datetime yang tidak diindeks:

  • Jelaskan rencana menunjukkan nilai yang sama untuk ketiga pilihan (323168)
  • Tetapi pemenangnya adalah AskTom (dengan analitik mengikuti di belakang)

Memilih 10 baris pertama yang dilakukan:

  • AskTom: 28-30 detik
  • Analitik: 33-37 detik
  • Alternatif singkat: 110-140 detik

Memilih baris antara 100.000 dan 100.010:

  • AskTom: 60 detik
  • Analitik: 100 detik

Memilih baris antara 9,000,000 dan 9,000,010:

  • AskTom: 130 detik
  • Analitik: 150 detik
zeldi
sumber
Kerja bagus. Apakah Anda mencoba alternatif singkat dengan antara alih-alih> = dan <=?
Mathieu Longtin
4
@MathieuLongtin BETWEENhanyalah sebuah singkatan untuk >= AND <=( stackoverflow.com/questions/4809083/between-clause-versus-and )
wweicker
1
zeldi - Versi apa ini? Oracle telah membuat peningkatan kinerja analitik di 11.1. dan 11.2.
Leigh Riffel
@Leigh Riffel Itu 10.2.0.5; suatu hari saya mungkin membutuhkan waktu dan juga memeriksa versi 11i.
zeldi
5
Saya menjalankan beberapa tes cepat dan mendapatkan hasil yang sama untuk 12c. offsetSintaks baru memiliki rencana dan kinerja yang sama dengan pendekatan analitik.
Jon Heller
55

Solusi analitik dengan hanya satu kueri bersarang:

SELECT * FROM
(
   SELECT t.*, Row_Number() OVER (ORDER BY name) MyRow FROM sometable t
) 
WHERE MyRow BETWEEN 10 AND 20;

Rank()dapat diganti Row_Number()tetapi dapat mengembalikan lebih banyak catatan daripada yang Anda harapkan jika ada nilai duplikat untuk nama.

Leigh Riffel
sumber
3
Saya suka analitik. Anda mungkin ingin mengklarifikasi apa perbedaan perilaku antara Rank () dan Row_Number ().
Dave Costa
Memang, tidak yakin mengapa saya tidak memikirkan duplikat. Jadi, dalam hal ini jika ada nilai duplikat untuk nama maka RANK dapat memberikan lebih banyak catatan daripada yang Anda harapkan karena itu Anda harus menggunakan Row_Number.
Leigh Riffel
Jika menyebutkan rank()itu juga perlu dicatat dense_rank()yang mungkin lebih berguna untuk kontrol output karena yang terakhir tidak "melewati" angka, sedangkan rank()bisa. Dalam kasus apa pun untuk pertanyaan row_number()ini paling cocok. Satu lagi tidak adalah teknik ini berlaku untuk db yang mendukung fungsi yang disebutkan.
Used_By_Already
28

Pada Oracle 12c (lihat klausa pembatas baris dalam referensi SQL ):

SELECT * 
FROM sometable
ORDER BY name
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
beldaz
sumber
53
Dan tentu saja, mereka harus menggunakan sintaks yang sama sekali berbeda dari orang lain sejauh ini
Mathieu Longtin
9
Jelas setelah duduk dengan semua vendor lain untuk menyetujui LIMITdalam SQL: 2008 mereka kemudian harus mengambil daun dari buku Microsoft dan melanggar standar.
beldaz
1
Menariknya saya mendengar baru-baru ini bahwa standar terbaru termasuk sintaks ini, jadi mungkin Oracle mendorongnya terlebih dahulu sebelum mengimplementasikan. Bisa dibilang itu lebih fleksibel daripadaLIMIT ... OFFSET
beldaz
3
@ Serek: Ya, tidak mengikuti standar sangat disesalkan. Tetapi fungsionalitas yang baru diperkenalkan di 12cR1 lebih kuat dari sekedar LIMIT n, m(Lihat jawaban saya). Kemudian lagi, Oracle seharusnya diimplementasikan LIMIT n, msebagai gula sintaksis, karena setara dengan OFFSET n ROWS FETCH NEXT m ROWS ONLY.
sampathsris
10
@Derek: Sebenarnya, saya baru memperhatikan komentar ini dalam manual PostgreSQL postgresql.org/docs/9.0/static/sql-select.html#AEN69535 "Klausa LIMIT dan OFFSET adalah sintaksis spesifik PostgreSQL, juga digunakan oleh MySQL. SQL : Standar 2008 telah memperkenalkan klausa OFFSET ... FETCH {FIRST | NEXT} ... untuk fungsi yang sama ". Jadi LIMIT tidak pernah menjadi bagian dari standar.
beldaz
14

Pertanyaan pagination dengan pemesanan benar-benar rumit di Oracle.

Oracle menyediakan pseudocolumn ROWNUM yang mengembalikan nomor yang menunjukkan urutan di mana database memilih baris dari tabel atau sekumpulan tampilan gabungan.

ROWNUM adalah pseudocolumn yang membuat banyak orang terlibat masalah. Nilai ROWNUM tidak ditetapkan secara permanen ke baris (ini adalah kesalahpahaman umum). Mungkin membingungkan ketika nilai ROWNUM benar-benar ditetapkan. Nilai ROWNUM ditetapkan ke baris setelah melewati predikat filter permintaan tetapi sebelum agregasi permintaan atau penyortiran .

Terlebih lagi, nilai ROWNUM bertambah hanya setelah ditetapkan.

Inilah sebabnya mengapa permintaan followin tidak menghasilkan baris:

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

Baris pertama hasil kueri tidak lulus predikat ROWNUM> 1, jadi ROWNUM tidak naik ke 2. Karena alasan ini, tidak ada nilai ROWNUM yang lebih besar dari 1, akibatnya, kueri tidak mengembalikan baris.

Kueri yang didefinisikan dengan benar akan terlihat seperti ini:

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

Cari tahu lebih lanjut tentang pertanyaan pagination di artikel saya di blog Vertabelo :

Bartek
sumber
2
Baris pertama dari hasil kueri tidak lulus ROWNUM> 1 predikat (...) - upvote untuk menjelaskan ini.
Piotr Dobrogost
6

SQL Standard

Seperti yang saya jelaskan dalam artikel ini , SQL: 2008 Standard menyediakan sintaks berikut untuk membatasi set hasil SQL:

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

Oracle 11g dan versi yang lebih lama

Sebelum versi 12c, untuk mengambil catatan Top-N, Anda harus menggunakan tabel turunan dan pseudocolumn ROWNUM:

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

Kurang pernyataan SELECT. Juga, kurang memakan kinerja. Kredit ke: [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
sumber
2
Lebih jauh lagi, itu jawaban yang benar-benar salah. Pertanyaannya adalah tentang membatasi SETELAH penyortiran. Jadi rownum harus keluar dari subquery.
BitLord
5

Sebagai perpanjangan dari jawaban yang diterima Oracle secara internal menggunakan ROW_NUMBER/RANKfungsi. OFFSET FETCHsintaksis adalah gula sintaksis.

Itu bisa diamati dengan menggunakan DBMS_UTILITY.EXPAND_SQL_TEXTprosedur:

Mempersiapkan sampel:

CREATE TABLE rownum_order_test (
  val  NUMBER
);

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

Pertanyaan:

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

teratur:

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 <> demo biola

Mengambil teks SQL yang diperluas:

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 TIESdiperluas sebagai 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

dan 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
sumber
3

Jika Anda tidak menggunakan Oracle 12C, Anda dapat menggunakan permintaan TOP N seperti di bawah ini.

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

Anda bahkan dapat memindahkan ini dari klausa dengan klausa sebagai berikut

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

Di sini sebenarnya kita membuat tampilan sebaris dan mengganti nama rownum sebagai rnum. Anda dapat menggunakan rnum dalam kueri utama sebagai kriteria filter.

sandi
sumber
1
Dalam kasus saya ini tidak mengembalikan baris yang tepat. Apa yang saya lakukan untuk memperbaikinya adalah dengan melakukan ORDER BYdan rownumsecara terpisah. Pada dasarnya saya membuat sub-query yang memiliki ORDER BYklausa .
Patrick Gregorio
Turunkan karena itu jawaban yang salah. Pertanyaannya adalah tentang membatasi setelah penyortiran jadi rownumharus di luar subquery.
Piotr Dobrogost
@PiotrDobrogost rownum hanya di luar.
sandi
2

Saya mulai mempersiapkan ujian Oracle 1z0-047, divalidasi terhadap 12c Saat mempersiapkannya, saya menemukan peningkatan 12c yang dikenal sebagai 'FETCH FIRST'. Memungkinkan Anda untuk mengambil baris / batas baris sesuai kenyamanan Anda. Beberapa opsi tersedia dengannya

- 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

Contoh:

Select * from XYZ a
order by a.pqr
FETCH FIRST 10 ROWS ONLY
arjun gaur
sumber
3
stackoverflow.com/a/26051830/635608 - ini sudah disediakan di jawaban lain. Harap jangan memposting hal-hal yang sudah diposting bulan lalu.
Mat
1
oh tentu, tidak melalui setiap jawaban, saya menemukan yang subquery sejak awal, akan mengingatnya.
arjun gaur
1
select * FROM (SELECT 
   ROW_NUMBER() OVER (ORDER BY sal desc),* AS ROWID, 
 FROM EMP ) EMP  where ROWID=5

lebih besar dari nilai yang ditemukan

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

kurang dari nilai menemukan

select * FROM (SELECT 
       ROW_NUMBER() OVER (ORDER BY sal desc),* AS ROWID, 
     FROM EMP ) EMP  where ROWID=5
Mehul Akabari
sumber
Downvote sebagai ROW_NUMBER()solusi berbasis telah diposting oleh Leigh Riffel. Dalam kecanduan ada kesalahan sintaksis dalam kode yang ditampilkan.
Piotr Dobrogost
1

Untuk setiap baris yang dikembalikan oleh kueri, pseudocolumn ROWNUM mengembalikan nomor yang menunjukkan urutan Oracle memilih baris dari tabel atau set baris yang digabungkan. Baris pertama yang dipilih memiliki ROWNUM 1, yang kedua memiliki 2, dan seterusnya.

  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 

Saya telah menerapkan ini di oracleserver11.2.0.1.0

Sumesh TG
sumber
downvote sebagai pertanyaan bertanya tentang membatasi baris yang dipesan dan Anda bahkan tidak memiliki pesanan
Piotr Dobrogost
@PiotrDobrogost Memahami itu bukan tugas besar, memesan kata kunci umum untuk semua rdbms hanya batasnya yang berubah.
Sumesh TG
-1

Dalam hal SQL-Developer, secara otomatis hanya mengambil 50 baris pertama. Dan jika kita gulir ke bawah, ia mengambil 50 baris lagi dan seterusnya!

Karenanya kita tidak perlu mendefinisikan, dalam hal alat sql-developer!

Aditya Goel
sumber
-3

Di oracle

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

VAL

    10
    10
     9
     9
     8

5 baris dipilih.

SQL>

Rakesh
sumber
7
Anda harus menentukan bahwa ini berlaku mulai dari Oracle 12c, dan bahwa Anda menyalin / menempelnya dari suatu tempat - harap selalu mengutip sumber Anda.
Mat
Sumbernya adalah @Mat ini . Dan Rakesh, tolong coba setidaknya untuk mengadaptasi jawaban untuk pertanyaan awal. Saya juga memberikan jawaban yang mengutip sumber yang sama, tetapi saya mencoba menjadi komprehensif dan mengutip sumber aslinya.
sampathsris
-4

(Belum diuji) sesuatu seperti ini dapat melakukan pekerjaan

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

Ada juga peringkat fungsi analitik, yang dapat Anda gunakan untuk memesan.

EvilTeach
sumber
2
Ini tidak akan mengembalikan satu baris karena ROWNUM adalah kolom pada resultset sehingga kondisi WHERE terakhir akan selalu salah. Plus, Anda tidak dapat menggunakan ROWNUM dan ORDER OLEH ORDER jaminan.
Ben
2
Luar biasa. Biarkan ini di sini sebagai peringatan bagi orang lain.
EvilTeach
-5

Sama seperti di atas dengan koreksi. Bekerja tetapi jelas tidak cantik.

   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

Jujur, lebih baik menggunakan jawaban di atas.

merangsang
sumber
5
Ini tidak benar karena klausa WHERE dievaluasi sebelum ORDER BY.
Ben
3
Menariknya dicuri dari jawaban buruk saya di bawah ini.
EvilTeach