2012-06-25 48 views
85

Sự khác nhau giữa các hàm RANK()DENSE_RANK() là gì? Làm thế nào để tìm ra mức lương thứ n trong bảng emptbl sau?Sự khác nhau giữa hàm RANK() và DENSE_RANK() trong oracle là gì?

DEPTNO EMPNAME SAL 
------------------------------ 
10  rrr 10000.00 
11  nnn 20000.00 
11  mmm 5000.00 
12  kkk 30000.00 
10  fff 40000.00 
10  ddd 40000.00 
10  bbb 50000.00 
10  ccc 50000.00 

Nếu trong bảng dữ liệu có nulls, điều gì sẽ xảy ra nếu tôi muốn tìm hiểu nth lương?

Trả lời

146

RANK cung cấp cho bạn thứ hạng trong phân vùng đã sắp xếp của bạn. Các mối quan hệ được chỉ định cùng một cấp bậc, với thứ hạng tiếp theo bị bỏ qua. Vì vậy, nếu bạn có 3 mục ở cấp 2, xếp hạng tiếp theo được liệt kê sẽ được xếp hạng 5.

DENSE_RANK lại cho bạn xếp hạng trong phân vùng đã sắp xếp của bạn, nhưng xếp hạng liên tiếp. Không có thứ hạng nào bị bỏ qua nếu có xếp hạng với nhiều mục.

Đối với các giá trị rỗng, nó phụ thuộc vào mệnh đề ORDER BY. Đây là một kịch bản thử nghiệm đơn giản mà bạn có thể chơi để xem điều gì sẽ xảy ra:

with q as (
select 10 deptno, 'rrr' empname, 10000.00 sal from dual union all 
select 11, 'nnn', 20000.00 from dual union all 
select 11, 'mmm', 5000.00 from dual union all 
select 12, 'kkk', 30000 from dual union all 
select 10, 'fff', 40000 from dual union all 
select 10, 'ddd', 40000 from dual union all 
select 10, 'bbb', 50000 from dual union all 
select 10, 'xxx', null from dual union all 
select 10, 'ccc', 50000 from dual) 
select empname, deptno, sal 
    , rank() over (partition by deptno order by sal nulls first) r 
    , dense_rank() over (partition by deptno order by sal nulls first) dr1 
    , dense_rank() over (partition by deptno order by sal nulls last) dr2 
from q; 

EMP  DEPTNO  SAL   R  DR1  DR2 
--- ---------- ---------- ---------- ---------- ---------- 
xxx   10      1   1   4 
rrr   10  10000   2   2   1 
fff   10  40000   3   3   2 
ddd   10  40000   3   3   2 
ccc   10  50000   5   4   3 
bbb   10  50000   5   4   3 
mmm   11  5000   1   1   1 
nnn   11  20000   2   2   2 
kkk   12  30000   1   1   1 

9 rows selected. 

Here's a link để giải thích và một số ví dụ.

+6

rất tốt id ea sử dụng chọn union tất cả từ dual để tạo dữ liệu mẫu mà không cần tạo bất kỳ bảng nào –

+0

@ Jean-ChristopheBlanchard mặc dù bạn có thể dễ dàng sử dụng mệnh đề 'values'. – Wildcard

+1

@Wildcard Trong PG, vâng. Trong Oracle, * không *. Ít nhất là không phải của 11. Tôi đã không chạy vào 12 trong prod được nêu ra. – jpmc26

1
select empno 
     ,salary 
     ,row_number() over(order by salary desc) as Serial 
     ,Rank() over(order by salary desc) as rank 
     ,dense_rank() over(order by salary desc) as denseRank 
from emp ; 

Row_number() -> Được sử dụng để tạo ra hàng loạt số

Dense_rank() sẽ cung cấp cho cấp bậc liên tục nhưng rank sẽ bỏ qua thứ hạng trong trường hợp đụng độ của các cấp bậc.

6
SELECT empno, 
     deptno, 
     sal, 
     RANK() OVER (PARTITION BY deptno ORDER BY sal) "rank" 
FROM emp; 

    EMPNO  DEPTNO  SAL  rank 
---------- ---------- ---------- ---------- 
     7934   10  1300   1 
     7782   10  2450   2 
     7839   10  5000   3 
     7369   20  800   1 
     7876   20  1100   2 
     7566   20  2975   3 
     7788   20  3000   4 
     7902   20  3000   4 
     7900   30  950   1 
     7654   30  1250   2 
     7521   30  1250   2 
     7844   30  1500   4 
     7499   30  1600   5 
     7698   30  2850   6 


SELECT empno, 
     deptno, 
     sal, 
     DENSE_RANK() OVER (PARTITION BY deptno ORDER BY sal) "rank" 
FROM emp; 

    EMPNO  DEPTNO  SAL  rank 
---------- ---------- ---------- ---------- 
     7934   10  1300   1 
     7782   10  2450   2 
     7839   10  5000   3 
     7369   20  800   1 
     7876   20  1100   2 
     7566   20  2975   3 
     7788   20  3000   4 
     7902   20  3000   4 
     7900   30  950   1 
     7654   30  1250   2 
     7521   30  1250   2 
     7844   30  1500   3 
     7499   30  1600   4 
     7698   30  2850   5 
54

This article here nicely explains it. Về cơ bản, bạn có thể nhìn vào nó như vậy:

CREATE TABLE t AS 
SELECT 'a' v FROM dual UNION ALL 
SELECT 'a' FROM dual UNION ALL 
SELECT 'a' FROM dual UNION ALL 
SELECT 'b' FROM dual UNION ALL 
SELECT 'c' FROM dual UNION ALL 
SELECT 'c' FROM dual UNION ALL 
SELECT 'd' FROM dual UNION ALL 
SELECT 'e' FROM dual; 

SELECT 
    v, 
    ROW_NUMBER() OVER (ORDER BY v) row_number, 
    RANK()  OVER (ORDER BY v) rank, 
    DENSE_RANK() OVER (ORDER BY v) dense_rank 
FROM t 
ORDER BY v; 

trên sẽ mang lại:

+---+------------+------+------------+ 
| V | ROW_NUMBER | RANK | DENSE_RANK | 
+---+------------+------+------------+ 
| a |   1 | 1 |   1 | 
| a |   2 | 1 |   1 | 
| a |   3 | 1 |   1 | 
| b |   4 | 4 |   2 | 
| c |   5 | 5 |   3 | 
| c |   6 | 5 |   3 | 
| d |   7 | 7 |   4 | 
| e |   8 | 8 |   5 | 
+---+------------+------+------------+ 

Nói cách

  • ROW_NUMBER() thuộc tính một giá trị duy nhất mỗi hàng
  • RANK() thuộc tính số cùng hàng với giá trị tương tự, để lại "lỗ"
  • DENSE_RANK() thuộc tính số cùng hàng với giá trị như nhau, không để lại "lỗ"
+1

Điều đó thật tuyệt :) – nanosoft

+0

Lỗi: Lỗi SQL: ORA-00923: TỪ từ khóa không tìm thấy ở đâu được mong đợi – zloctb

+0

@zloctb: Có, cảm ơn bạn. đã sửa –

1

Sự khác biệt duy nhất giữa RANK () và các hàm DENSE_RANK() trong trường hợp có “tie”; nghĩa là, trong trường hợp nhiều giá trị trong một tập hợp có cùng thứ hạng. Trong trường hợp như vậy, hàm RANK() sẽ gán "xếp hạng" không liên tiếp cho các giá trị trong tập hợp (dẫn đến khoảng trống giữa các giá trị xếp hạng nguyên khi có tie), trong khi DENSE_RANK() sẽ gán các thứ hạng liên tiếp cho các giá trị trong thiết lập (do đó sẽ không có khoảng trống giữa các giá trị xếp hạng nguyên trong trường hợp của một tie).

Ví dụ: hãy xem tập hợp {25, 25, 50, 75, 75, 100}. Đối với một tập hợp như vậy, hàm RANK() sẽ trả về {1, 1, 3, 4, 4, 6} (lưu ý rằng các giá trị 2 và 5 bị bỏ qua), trong khi DENSE_RANK() sẽ trả về {1,1,2,3, 3,4}.

2

xếp hạng(): Được sử dụng để xếp hạng bản ghi trong một nhóm hàng.

dense_rank(): Hàm DENSE_RANK hoạt động giống như hàm RANK ngoại trừ chức năng gán các cấp bậc liên tiếp.

Query -

select 
    ENAME,SAL,RANK() over (order by SAL) RANK 
from 
    EMP; 

Output -

+--------+------+------+ 
| ENAME | SAL | RANK | 
+--------+------+------+ 
| SMITH | 800 | 1 | 
| JAMES | 950 | 2 | 
| ADAMS | 1100 | 3 | 
| MARTIN | 1250 | 4 | 
| WARD | 1250 | 4 | 
| TURNER | 1500 | 6 | 
+--------+------+------+ 

Query -

select 
    ENAME,SAL,dense_rank() over (order by SAL) DEN_RANK 
from 
    EMP; 

Output -

+--------+------+-----------+ 
| ENAME | SAL | DEN_RANK | 
+--------+------+-----------+ 
| SMITH | 800 |   1 | 
| JAMES | 950 |   2 | 
| ADAMS | 1100 |   3 | 
| MARTIN | 1250 |   4 | 
| WARD | 1250 |   4 | 
| TURNER | 1500 |   5 | 
+--------+------+-----------+ 
Các vấn đề liên quan