2012-02-11 29 views
17

Tôi đã cố gắng truy vấn dưới đây:Lựa chọn hàng thứ hai của một bảng sử dụng rownum

select empno from (
        select empno 
        from emp 
        order by sal desc 
       ) 
where rownum = 2 

này không được trả lại bất kỳ hồ sơ.

Khi tôi cố gắng truy vấn này

select rownum,empno from (
         select empno from emp order by sal desc) 

Nó mang lại cho tôi kết quả này:

ROWNUM EMPNO  
1  7802   
2  7809  
3  7813  
4  7823 

bất cứ ai có thể cho tôi biết vấn đề với truy vấn đầu tiên của tôi là gì? Tại sao nó không trả lại bất kỳ bản ghi nào khi tôi thêm bộ lọc ROWNUM?

Trả lời

44

Để giải thích hành vi này, chúng ta cần phải hiểu làm thế nào Oracle xử lý ROWNUM. Khi gán ROWNUM cho một hàng, Oracle bắt đầu tại 1 và chỉ chỉ tăng giá trị khi một hàng được chọn; nghĩa là, khi tất cả các điều kiện trong mệnh đề WHERE được đáp ứng. Kể từ khi tình trạng của chúng tôi đòi hỏi rằng ROWNUM là lớn hơn 2, không có hàng được lựa chọn và ROWNUM là không bao giờ tăng lên vượt quá 1.

Điểm mấu chốt là các điều kiện như sau đây sẽ làm việc như mong đợi.

.. WHERE rownum = 1;

.. WHERE rownum < = 10;

Mặc dù các truy vấn có các điều kiện này sẽ luôn trả về 0 hàng.

.. WHERE rownum = 2;

.. WHERE rownum> 10;

Quoted from Understanding Oracle rownum

Bạn nên sửa đổi bạn truy vấn theo cách này để làm việc:

select empno 
from 
    (
    select empno, rownum as rn 
    from (
      select empno 
      from emp 
      order by sal desc 
     ) 
    ) 
where rn=2; 

EDIT: Tôi đã sửa chữa các truy vấn để có được những rownum sau đơn đặt hàng của sal desc

+0

: Cảm ơn lời giải thích +1 ... truy vấn không đáng giá vì tôi muốn các rownum của các hồ sơ lấy trên cơ sở thứ tự của sal desc, truy vấn dint làm việc nếu chúng ta đặt rownum trong truy vấn bên trong, nó sẽ cho chúng ta rownum của các hồ sơ của emp bảng, không phải của các dữ liệu được sắp xếp .... Cảm ơn bạn đã giải thích –

+0

Câu trả lời hay (+1), nhưng truy vấn bạn đề xuất sẽ không hoạt động chính xác và trả lại nhân viên trả lương cao thứ 2. Bạn sẽ cần một cấp truy vấn phụ khác để đảm bảo ROWNUM được gán _after_ ORDER BY. –

+0

@BrankoDimitrijevic bạn nói đúng. Tôi sẽ sửa câu trả lời –

1

thử điều này:

SELECT ROW_NUMBER() OVER (ORDER BY empno) AS RowNum, 
     empno 
FROM tableName 
WHERE RowNumber = 2; 

Snippet Từ Nguồn:

SELECT last_name FROM 
     (SELECT last_name, ROW_NUMBER() OVER (ORDER BY last_name) R FROM employees) 
WHERE R BETWEEN 51 and 100 

REFERENCE

+0

: Cảm ơn các giải pháp, nhưng tôi không tìm kiếm các giải pháp ở đây, tôi đang tìm kiếm nguyên nhân tại sao truy vấn trên không hoạt động .. –

+0

Tin rằng mệnh đề 'where' của bạn nên có' RowNum' thay vì 'RowNumber' –

7

Trong truy vấn đầu tiên đầu tiên, hàng đầu tiên sẽ có ROWNUM = 1 do đó sẽ bị từ chối. Hàng thứ hai cũng sẽ có ROWNUM = 1 (vì hàng trước đó bị từ chối) và cũng bị từ chối, hàng thứ ba cũng sẽ có ROWNUM = 1 (vì tất cả các hàng trước khi nó bị từ chối) và cũng bị từ chối vv ... Mạng kết quả là tất cả các hàng đều bị từ chối.

Số truy vấn thứ hai không được trả về kết quả bạn nhận được. Nó phải chỉ định chính xác ROWNUM sau ORDER BY.

Như một hệ quả của tất cả điều này, bạn cần sử dụng không 2 nhưng 3 cấp truy vấn con, như thế này:

SELECT EMPNO, SAL FROM (-- Make sure row is not rejected before next ROWNUM can be assigned. 
    SELECT EMPNO, SAL, ROWNUM R FROM (-- Make sure ROWNUM is assigned after ORDER BY. 
     SELECT EMPNO, SAL 
     FROM EMP 
     ORDER BY SAL DESC 
    ) 
) 
WHERE R = 2 

Kết quả:

EMPNO     SAL      
---------------------- ---------------------- 
3      7813     
+0

+1 để giải thích chi tiết về truy vấn –

+0

Pitty điều này trở nên phức tạp hơn nhiều khi chọn * thay vào đó nếu bạn không muốn sự trở lại như là một phần của đầu ra. Đặc biệt là khi tham gia hoặc truy vấn một lượt xem. – user6856

0

chọn empno từ (
chọn empno, rownum as rum
từ emp,
đặt hàng bởi sal desc
)
nơi rum = 2;

+0

Xin chào Deepak và chào mừng bạn đến với SO! Trong khi câu trả lời của bạn có thể chính xác, giá trị gia tăng so với câu trả lời đã được chấp nhận là gì? Imho câu trả lời của bạn là dư thừa và không thêm bất kỳ thông tin hữu ích nào. Do đó, không có khả năng nhận được bất kỳ xác nhận tích cực nào. Tập trung vào các câu hỏi chưa được trả lời hoặc thêm câu trả lời với giá trị bổ sung để đạt được một số danh tiếng. – cfi

-1

Bạn có thể sử dụng RANK hoặc DENSE_RANK để đạt được những gì bạn đang cố gắng đạt được ở đây.

+0

bạn nên cung cấp ví dụ – Austin

0
Select * From (SELECT *, 
    ROW_NUMBER() OVER(ORDER BY column_name DESC) AS mRow 

FROM table_name 

WHERE condition) as TT 
Where TT.mRow=2; 
1

Đối với hàng thứ n sử dụng rownum trong oracle:

select * from TEST WHERE ROWNUM<=n 
MINUS 
select * from TEST WHERE ROWNUM<=(n-1); 

Ví dụ cho hàng thứ hai:

select * from TEST WHERE ROWNUM<=2 
MINUS 
select * from TEST WHERE ROWNUM<=1; 
+0

Kamruzzaman: Phải có tiêu chí để tìm nạp bản ghi thứ n, ví dụ như mức lương cao thứ hai, không có logic nào trong truy vấn của bạn –

Các vấn đề liên quan