Яка різниця між функціями RANK () та DENSE_RANK () в oracle?


150

У чому різниця між RANK()і DENSE_RANK()функціями? Як дізнатися n-ту зарплату в наступній emptblтаблиці?

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, що буде, якщо я хочу дізнатися nthзарплату?

Відповіді:


242

RANK дає вам рейтинг в упорядкованому розділі. Зв'язки присвоюються одного і того ж рангу, а наступний рейтинг пропускається. Отже, якщо у вас є 3 позиції на 2 рангу, наступний перелічений ранг буде 5 місцем.

DENSE_RANK знову дає вам рейтинг у упорядкованому розділі, але ранги є послідовними. Жодні ранги не пропускаються, якщо є ранги з кількома елементами.

Що стосується нулів, це залежить від пункту ЗАМОВЛЕННЯ ПО. Ось простий тестовий сценарій, з яким ви можете грати, щоб побачити, що відбувається:

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.

Ось посилання на гарне пояснення та кілька прикладів.


14
дуже гарна ідея використовувати вибір об’єднання, все від подвійного, щоб генерувати вибіркові дані, не створюючи жодної таблиці
Жан-Крістоф Бланшард

@ Jean-ChristopheBlanchard, хоча ти можеш так само легко використовувати valuesпункт.
Wildcard

1
@Wildcard У PG так. В Oracle немає . Принаймні не станом на 11. Я ще не наткнувся на 12 у продажі.
jpmc26

Видалити from dualдля отримання цих даних у Redshift
Gaurav

4
Іван, RANK дає мені уявлення, де я відносно всіх тих, хто переді мною. DENSE_RANK каже мені абсолютний ранг. У мене може бути друга найвища зарплата, але переді мною може бути 100 людей. Хто краще, залежить від питання, на який я відповідаю.
DCookie

93

Ця стаття тут непогано пояснює це. По суті, ви можете розглядати це як таке:

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() атрибує той самий номер рядка одному і тому ж значенню, не залишаючи «дірок»

Помилка: помилка SQL: ORA-00923: ключове слово FROM не знайдено там, де очікується
zloctb

9
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

8

rank () : використовується для ранжування запису в групі рядків.

щільний_rank () : Функція DENSE_RANK діє як функція RANK, за винятком того, що вона присвоює послідовні ранги.

Запит -

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

Вихід -

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

Запит -

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

Вихід -

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

2
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() -> Використовується для генерації серійного номера

Dense_rank() буде давати безперервний ранг, але ранг буде пропускати ранг у разі зіткнення рангу.


2

Єдина відмінність між функціями RANK () і DENSE_RANK () полягає у випадках, коли існує "краватка"; тобто у випадках, коли декілька значень у множині мають однаковий рейтинг. У таких випадках RANK () присвоює непослідовні «ранги» значенням у наборі (у результаті чого виникають проміжки між цілими значеннями ранжирування, коли є прив'язка), тоді як DENSE_RANK () присвоює значення послідовних значень встановити (так що у випадку зв'язання не буде зазорів між цілими значеннями ранжування).

Наприклад, розглянемо множину {25, 25, 50, 75, 75, 100}. Для такого набору RANK () повернеться {1, 1, 3, 4, 4, 6} (зауважте, що значення 2 і 5 пропускаються), тоді як DENSE_RANK () повернеться {1,1,2,3, 3,4}.


1

Функція SQL Rank () генерує ранг даних у впорядкованому наборі значень, але наступний ранг після попереднього рангу - це рядковий номер цього конкретного рядка. З іншого боку, функція SQL Dense_Rank () генерує наступне число замість того, щоб генерувати номер рядка. Нижче наведено приклад SQL, який уточнить концепцію:

Select ROW_NUMBER() over (order by Salary) as RowNum, Salary, 
RANK() over (order by Salary) as Rnk, 
DENSE_RANK() over (order by Salary) as DenseRnk from (
Select 1000 as Salary union all
Select 1000 as Salary union all
Select 1000 as Salary union all
Select 2000 as Salary union all
Select 3000 as Salary union all
Select 3000 as Salary union all
Select 8000 as Salary union all
Select 9000 as Salary) A

Це призведе до наступного виходу:

----------------------------
RowNum  Salary  Rnk DenseRnk
----------------------------
1       1000    1   1
2       1000    1   1
3       1000    1   1
4       2000    4   2
5       3000    5   3
6       3000    5   3
7       8000    7   4
8       9000    8   5

0

Ранг та щільний ранг дає ранг у наборі даних про розподіл.

Ранг (): не дає вам послідовних цілих чисел.

Dense_rank (): дає вам послідовні цілі числа.

введіть тут опис зображення

На наведеному вище малюнку ранг 10008 zip - це 2 за допомогою функції щільно_rank () та 24 за функцією rank (), оскільки він вважає число рядків.


0

Rank(), Dense_rank(), row_number() Це все функції вікна, тобто спочатку вони виконують функцію вікна над впорядкованим введенням. Ці вікна мають різні функціональні можливості, прикріплені до нього на основі вимоги. Ось вище 3:

row_number()

Починаючи з row_number()цього, як це лежить в основі цих пов'язаних функцій вікна. row_number()як випливає з назви, дає унікальний номер набору рядків, над якими його застосовано. Аналогічно даванню серійного номера кожному рядку.

Rank()

Підрив row_number()може бути сказаний як rank(). Rank () використовується для того, щоб дати той самий серійний номер тим упорядкованим наборам рядків, які є дублікатами, але він як і раніше зберігає підрахунок дорівнює такому ж, як і row_number()для всіх тих, хто після дублікатів rank () означає, як знизу, наприклад. Для даних 2 row_number () = rank () значення обох просто відрізняється у вигляді дублікатів.

Data row_number() rank() dense_rank() 
    1         1                    1       1
    1         2                    1       1
    1         3                    1       1
    2         4                    4       2

Нарешті,

Dense_rank () - це розширена версія ranga (), як випливає з назви, тому що, як видно з наведеного вище прикладу rank () = thick_rank () для всіх даних 1, але тільки для даних 2 він відрізняється формою, зберігає порядок rank () від попереднього рангу (), а не фактичні дані


0

Єдина відмінність між функціями RANK () і DENSE_RANK () полягає у випадках, коли існує "краватка"; тобто у випадках, коли декілька значень у множині мають однаковий рейтинг. У таких випадках RANK () присвоює непослідовні «ранги» значенням у наборі (у результаті чого виникають проміжки між цілими значеннями ранжирування, коли є прив'язка), тоді як DENSE_RANK () присвоює значення послідовних значень встановити (так що у випадку зв'язання не буде зазорів між цілими значеннями ранжування).

Наприклад, розглянемо множину {30, 30, 50, 75, 75, 100}. Для такого набору RANK () повернеться {1, 1, 3, 4, 4, 6} (зауважте, що значення 2 і 5 пропускаються), тоді як DENSE_RANK () повернеться {1,1,2,3, 3,4}.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.