RANK() 和 DENSE_RANK() 函数在Oracle中有什么区别?

9 浏览
0 Comments

RANK() 和 DENSE_RANK() 函数在Oracle中有什么区别?

函数RANK()DENSE_RANK()的区别是什么?如何在以下emptbl表中找到第n个工资?

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

如果表格数据中有nulls,如果我想找出第n个工资,会发生什么?

admin 更改状态以发布 2023年5月20日
0
0 Comments

我在这篇文章中更详细地解释了这个问题。本质上,你可以看作如下:

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;

以上将产生:

+---+------------+------+------------+
| 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 |
+---+------------+------+------------+

用文字来描述

  • ROW_NUMBER() 给每行属性一个唯一的值
  • RANK() 给相同的值赋予相同的行数,留下空缺
  • DENSE_RANK() 给相同的值赋予相同的行数,不留空缺
0
0 Comments

RANK()函数会在有序分区内给出排名。排名相同的项会被分配相同的排名,而下一个排名会被跳过。因此,如果排名2有3个项目,则下一个排名将被排名为5。

DENSE_RANK()再次在有序分区内给出排名,但排名是连续的。如果有多个项目的排名,则不会跳过任何排名。

至于null值,这取决于ORDER BY子句。这里有一个简单的测试脚本可以让你看到发生的事情:

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.

这里是一个链接可以提供一些很好的解释和示例。

0