Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

CHỌN N hàng trên cùng mà không có ROWNUM?

Vì đây là bài tập về nhà, một gợi ý hơn là một câu trả lời. Bạn sẽ muốn sử dụng các hàm phân tích. ROW_NUMBER, RANK hoặc DENSE_RANK có thể hoạt động tùy thuộc vào cách bạn muốn xử lý các mối quan hệ.

Nếu các chức năng phân tích cũng không được phép, thì tùy chọn khác mà tôi có thể tưởng tượng - một tùy chọn mà bạn sẽ không bao giờ thực sự viết trong thực tế sẽ giống như

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

Về hiệu suất, tôi sẽ không dựa vào số COST từ kế hoạch truy vấn - đó chỉ là ước tính và nói chung không thể so sánh chi phí giữa các kế hoạch cho các câu lệnh SQL khác nhau. Tốt hơn hết là bạn nên xem xét điều gì đó giống như số lượng nhất quán mà truy vấn thực sự hoạt động và xem xét hiệu suất truy vấn sẽ mở rộng như thế nào khi số lượng hàng trong bảng tăng lên. Tùy chọn thứ ba sẽ kém hiệu quả hơn hoàn toàn so với hai tùy chọn còn lại đơn giản vì nó cần phải quét bảng NHÂN VIÊN hai lần.

Tôi không có bảng NHÂN VIÊN của bạn, vì vậy tôi sẽ sử dụng bảng EMP từ lược đồ SCOTT

Giải pháp hàm phân tích thực sự có 7 nhất quán cũng như giải pháp 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

Tuy nhiên, giải pháp COUNT (*) thực sự có 99 nhất quán được và phải quét toàn bộ bảng hai lần, vì vậy nó kém hiệu quả hơn 10 lần. Và quy mô sẽ tồi tệ hơn nhiều khi số lượng hàng trong bảng tăng lên

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. Lược đồ Star vs Snowflake trong kho dữ liệu?

  2. Chi phí trong bộ nhớ của Oracle

  3. ORA-28001:Mật khẩu đã hết hạn

  4. SINH () Hàm trong Oracle

  5. sql - ORA-00937:không phải là một hàm nhóm đơn