Oracle DENSE_RANK Function

Rank rows without gaps after ties with DENSE_RANK, and use it to find the second- or Nth-highest distinct value in each group.

DENSE_RANK ranks rows like RANK, giving tied rows the same rank, but without gaps afterward: 1, 2, 2, 3. That makes the rank count distinct values, which is exactly what questions such as "the second-highest salary" need.

Code for This Guide

The main examples are in the examples/analytic-functions folder of the Oracle Database 26ai code repository on GitHub, each with its output. They use NIMBUS, the sample schema of a fictional airline, which you can install with the scripts in the setup/nimbus folder.

They come from Oracle Database 26ai SQL and PL/SQL Book.

Syntax

dense_rank() over ([partition by expr [, ...]] order by expr [, ...])

The dense rank of a row is 1 plus the number of distinct ORDER BY values before it.

No Gaps after Ties

Example:

select customer_id, count(*) as bookings,
       row_number() over (order by count(*) desc) as row_number,
       rank()       over (order by count(*) desc) as rank,
       dense_rank() over (order by count(*) desc) as dense_rank
from   bookings
group  by customer_id
order  by bookings desc, customer_id
fetch  first 9 rows only;

Output:

   CUSTOMER_ID    BOOKINGS    ROW_NUMBER    RANK    DENSE_RANK
______________ ___________ _____________ _______ _____________
             5          15             1       1             1
             1          12             2       2             2
             3          12             3       2             2
             4          12             7       2             2
            18          12             5       2             2
            21          12             6       2             2
            49          12             4       2             2
            11          11            11       8             3
            13          11            10       8             3

9 rows selected.

Six customers share dense rank 2, and the customers with 11 bookings get 3, where RANK gives them 8.

The Second-Highest Salary

Because DENSE_RANK counts distinct values, DENSE_RANK = 2 finds the second-highest salary even when several people share the highest.

Example:

-- the second-highest distinct salary of each department
select department_id, salary as second_highest
from   (select distinct department_id, salary,
               dense_rank() over (partition by department_id order by salary desc) as dr
        from   employees
        where  department_id in (20, 30, 40))
where  dr = 2
order  by department_id;

Output:

   DEPARTMENT_ID    SECOND_HIGHEST
________________ _________________
              20             25500
              30             11800
              40             21000

DISTINCT in the inline view returns each salary once; without it, every employee with that salary would be listed.

Things to Know

  • Use DENSE_RANK for "Nth distinct value" questions, RANK for competition-style places, and ROW_NUMBER for one row per position.
  • In KEEP (DENSE_RANK FIRST ...), the same ranking selects the first or last rows of a group in an aggregate.
  • Like the other ranking functions, it requires ORDER BY in the OVER clause.

Related Guides

Conclusion

DENSE_RANK gives tied rows the same rank and continues without gaps, so ranks count distinct values. Use it to find the Nth-highest value per group, and choose RANK or ROW_NUMBER when gaps or unique numbers are wanted.

Vinish Kapoor
Vinish Kapoor

An Oracle ACE, author of four books on Oracle APEX, SQL and PL/SQL, and Oracle Forms, and a software developer building Oracle database applications since 2001.

guest

0 Comments
Oldest
Newest Most Voted