it-swarm.asia

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

Apakah ada cara untuk membuat permintaan Oracle berperilaku seperti itu mengandung klausa MySQL limit?

Dalam MySQL, saya bisa melakukan ini:

select * 
from sometable
order by name
limit 20,10

untuk mendapatkan baris ke 21 hingga 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 rownum pseudo-kolom, tetapi dievaluasi sebelum order by, yang artinya:

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

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

906
Mathieu Longtin

Mulai dari Oracle 12c R1 (12.1), ada is a baris yang membatasi klausa . Itu tidak menggunakan sintaks LIMIT akrab, tetapi dapat melakukan pekerjaan dengan lebih baik dengan lebih banyak opsi. Anda dapat menemukan sintaks lengkap di sini .

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 berikut dikutip dari halaman tertaut , dengan harapan mencegah pembusukan tautan.

Mempersiapkan

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 baris N 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 baris N pertama, jika Nth baris 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.
448
sampathsris

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 hasil terbatas di Oracle/AskTom untuk informasi lebih lanjut.

Perbarui : 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.

751
Kosi2801

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
173
zeldi

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 dengan Row_Number() tetapi mungkin mengembalikan lebih banyak catatan daripada yang Anda harapkan jika ada nilai duplikat untuk nama.

53
Leigh Riffel

Pada Oracle 12c (lihat klausa pembatasan baris di referensi SQL ):

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

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 diberikan ke baris setelah melewati predikat filter dari kueri tetapi sebelum agregasi kueri 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 Vertabelo blog:

11
Bartek

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;
6

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.

2
sandi
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 mencari tahu

select * FROM (SELECT 
       ROW_NUMBER() OVER (ORDER BY sal desc),* AS ROWID, 
     FROM EMP ) EMP  where ROWID=5
2
Mehul Akabari

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
1
arjun gaur

Untuk setiap baris yang dikembalikan oleh permintaan, 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 Oracle server 11.2.0.1.0

0
Sumesh TG