Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

MEMILIH N baris teratas tanpa ROWNUM?

Karena ini adalah pekerjaan rumah, petunjuk daripada jawaban. Anda akan ingin menggunakan fungsi analitik. ROW_NUMBER, RANK, atau DENSE_RANK dapat bekerja tergantung pada bagaimana Anda ingin menangani ikatan.

Jika fungsi analitik juga tidak diizinkan, opsi lain yang dapat saya bayangkan-- opsi yang tidak akan pernah Anda tulis dalam praktiknya, adalah seperti

SELECT name, salary
  FROM staff s1
 WHERE (SELECT COUNT(*)
          FROM staff s2
         WHERE s1.salary < s2.salary) <= 3

Berkenaan dengan kinerja, saya tidak akan bergantung pada nomor BIAYA dari paket kueri-- itu hanya perkiraan dan umumnya tidak mungkin untuk membandingkan biaya antara paket untuk pernyataan SQL yang berbeda. Anda jauh lebih baik melihat sesuatu seperti jumlah konsisten mendapatkan kueri yang sebenarnya dan mempertimbangkan bagaimana kinerja kueri akan diskalakan saat jumlah baris dalam tabel meningkat. Opsi ketiga akan menjadi kurang efisien secara radikal daripada dua lainnya hanya karena perlu memindai tabel STAFF dua kali.

Saya tidak punya tabel STAFF Anda, jadi saya akan menggunakan tabel EMP dari skema SCOTT

Solusi fungsi analitik sebenarnya menghasilkan 7 hasil yang konsisten seperti halnya solusi ROWNUM

Wrote file afiedt.buf

  1  select ename, sal
  2    from( select ename,
  3                 sal,
  4                 rank() over (order by sal) rnk
  5            from emp )
  6*  where rnk <= 3
SQL> /

ENAME             SAL
---------- ----------
smith             800
SM0               950
ADAMS            1110


Execution Plan
----------------------------------------------------------
Plan hash value: 3291446077

--------------------------------------------------------------------------------
-
| Id  | Operation                | Name | Rows  | Bytes | Cost (%CPU)| Time
|
--------------------------------------------------------------------------------
-
|   0 | SELECT STATEMENT         |      |    14 |   672 |     4  (25)| 00:00:01
|*  1 |  VIEW                    |      |    14 |   672 |     4  (25)| 00:00:01
|*  2 |   WINDOW SORT PUSHED RANK|      |    14 |   140 |     4  (25)| 00:00:01
|   3 |    TABLE ACCESS FULL     | EMP  |    14 |   140 |     3   (0)| 00:00:01
--------------------------------------------------------------------------------
-

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("RNK"<=3)
   2 - filter(RANK() OVER ( ORDER BY "SAL")<=3)


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          7  consistent gets
          0  physical reads
          0  redo size
        668  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          3  rows processed

SQL> select ename, sal
  2    from( select ename, sal
  3            from emp
  4           order by sal )
  5   where rownum <= 3;

ENAME             SAL
---------- ----------
smith             800
SM0               950
ADAMS            1110


Execution Plan
----------------------------------------------------------
Plan hash value: 1744961472

--------------------------------------------------------------------------------
| Id  | Operation               | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |      |     3 |   105 |     4  (25)| 00:00:01 |
|*  1 |  COUNT STOPKEY          |      |       |       |            |          |
|   2 |   VIEW                  |      |    14 |   490 |     4  (25)| 00:00:01 |
|*  3 |    SORT ORDER BY STOPKEY|      |    14 |   140 |     4  (25)| 00:00:01 |
|   4 |     TABLE ACCESS FULL   | EMP  |    14 |   140 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(ROWNUM<=3)
   3 - filter(ROWNUM<=3)


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          7  consistent gets
          0  physical reads
          0  redo size
        668  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          3  rows processed

Solusi COUNT(*), bagaimanapun, sebenarnya mendapatkan 99 yang konsisten dan harus melakukan pemindaian penuh tabel dua kali sehingga lebih dari 10 kali kurang efisien. Dan skalanya akan jauh lebih buruk karena jumlah baris dalam tabel bertambah

SQL> select ename, sal
  2    from emp e1
  3   where (select count(*) from emp e2 where e1.sal < e2.sal) <= 3;

ENAME             SAL
---------- ----------
JONES            2975
SCOTT            3000
KING             5000
FORD             3000
FOO


Execution Plan
----------------------------------------------------------
Plan hash value: 2649664444

----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |    14 |   140 |    24   (0)| 00:00:01 |
|*  1 |  FILTER             |      |       |       |            |          |
|   2 |   TABLE ACCESS FULL | EMP  |    14 |   140 |     3   (0)| 00:00:01 |
|   3 |   SORT AGGREGATE    |      |     1 |     4 |            |          |
|*  4 |    TABLE ACCESS FULL| EMP  |     1 |     4 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter( (SELECT COUNT(*) FROM "EMP" "E2" WHERE
              "E2"."SAL">:B1)<=3)
   4 - filter("E2"."SAL">:B1)


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         99  consistent gets
          0  physical reads
          0  redo size
        691  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          5  rows processed


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Menggunakan Dapper dengan prosedur tersimpan Oracle yang mengembalikan kursor

  2. Bagaimana cara mengembalikan RefCursor dari fungsi Oracle?

  3. Pemetaan Entitas Terpisah menghasilkan hasil yang tidak terduga dengan database oracle

  4. Saya perlu membuat tampilan yang menggabungkan tiga tabel, termasuk semua catatan dari tabel siswa dan kursus (ditampilkan di bawah)

  5. Apa itu Oracle SQL &PL/SQL? Semua Yang Perlu Diketahui Pemula