What is the difference between RANK(), DENSE_RANK(), and ROW_NUMBER()?
Answer
These are three window functions that assign sequential numbers to rows, but they handle ties (duplicate values) differently.
Key Differences
| Function | Handles Ties | Gaps After Ties | Use Case | 
|---|---|---|---|
| ROW_NUMBER() | Assigns unique numbers | N/A | Unique sequential numbering | 
| RANK() | Same rank for ties | Creates gaps | Traditional ranking with gaps | 
| DENSE_RANK() | Same rank for ties | No gaps | Continuous ranking without gaps | 
Sample Data
CREATE TABLE students (
    student_id INT,
    name VARCHAR(100),
    score INT
);
INSERT INTO students VALUES 
(1, 'Alice', 95),
(2, 'Bob', 87),
(3, 'Charlie', 92),
(4, 'Diana', 87),    -- Tie with Bob
(5, 'Eve', 87),      -- Tie with Bob and Diana
(6, 'Frank', 78),
(7, 'Grace', 92);    -- Tie with CharlieFunction Comparisons
All Three Functions Together
SELECT 
    name,
    score,
    ROW_NUMBER() OVER (ORDER BY score DESC) as row_num,
    RANK() OVER (ORDER BY score DESC) as rank_func,
    DENSE_RANK() OVER (ORDER BY score DESC) as dense_rank_func
FROM students
ORDER BY score DESC, name;
-- Result:
-- name    | score | row_num | rank_func | dense_rank_func
-- Alice   | 95    | 1       | 1         | 1
-- Charlie | 92    | 2       | 2         | 2
-- Grace   | 92    | 3       | 2         | 2  (tie)
-- Bob     | 87    | 4       | 4         | 3  (RANK skips 3)
-- Diana   | 87    | 5       | 4         | 3  (tie)
-- Eve     | 87    | 6       | 4         | 3  (tie)
-- Frank   | 78    | 7       | 7         | 4  (RANK skips 5,6)ROW_NUMBER()
Purpose: Assigns a unique sequential integer to each row.
Characteristics:
- Always unique - No two rows get the same number
 - Deterministic with ORDER BY - Same order produces same numbers
 - Arbitrary for ties - Ties get different numbers (order depends on implementation)
 
-- Basic ROW_NUMBER usage
SELECT 
    name,
    score,
    ROW_NUMBER() OVER (ORDER BY score DESC) as position
FROM students;
-- ROW_NUMBER with PARTITION BY
SELECT 
    name,
    score,
    grade_level,
    ROW_NUMBER() OVER (PARTITION BY grade_level ORDER BY score DESC) as rank_in_grade
FROM students;
-- Pagination using ROW_NUMBER
SELECT name, score
FROM (
    SELECT 
        name, 
        score,
        ROW_NUMBER() OVER (ORDER BY score DESC) as rn
    FROM students
) ranked
WHERE rn BETWEEN 3 AND 5;  -- Get rows 3-5RANK()
Purpose: Assigns the same rank to tied values, with gaps in subsequent rankings.
Characteristics:
- Ties get same rank - Equal values receive identical ranks
 - Creates gaps - Next rank skips numbers equal to tie count
 - Traditional ranking - Like Olympic medal rankings
 
-- Basic RANK usage
SELECT 
    name,
    score,
    RANK() OVER (ORDER BY score DESC) as rank_position
FROM students;
-- Find top 3 unique scores (handles ties)
SELECT DISTINCT
    score,
    RANK() OVER (ORDER BY score DESC) as rank_position
FROM students
WHERE RANK() OVER (ORDER BY score DESC) <= 3;
-- Rank within departments
SELECT 
    employee_name,
    department,
    salary,
    RANK() OVER (PARTITION BY department ORDER BY salary DESC) as dept_rank
FROM employees;DENSE_RANK()
Purpose: Assigns the same rank to tied values, without gaps in subsequent rankings.
Characteristics:
- Ties get same rank - Equal values receive identical ranks
 - No gaps - Next rank is always consecutive
 - Continuous sequence - Like academic grading systems
 
-- Basic DENSE_RANK usage
SELECT 
    name,
    score,
    DENSE_RANK() OVER (ORDER BY score DESC) as dense_rank_position
FROM students;
-- Find students in top 3 score categories
SELECT name, score
FROM (
    SELECT 
        name, 
        score,
        DENSE_RANK() OVER (ORDER BY score DESC) as dr
    FROM students
) ranked
WHERE dr <= 3;  -- Gets all students with top 3 distinct scores
-- Quartile ranking
SELECT 
    name,
    score,
    DENSE_RANK() OVER (ORDER BY score DESC) as rank_pos,
    CASE 
        WHEN DENSE_RANK() OVER (ORDER BY score DESC) <= 2 THEN 'Top Tier'
        WHEN DENSE_RANK() OVER (ORDER BY score DESC) <= 4 THEN 'Middle Tier'
        ELSE 'Lower Tier'
    END as tier
FROM students;Practical Use Cases
1. E-commerce Product Ranking
-- Product popularity ranking
SELECT 
    product_name,
    total_sales,
    ROW_NUMBER() OVER (ORDER BY total_sales DESC) as sales_position,
    RANK() OVER (ORDER BY total_sales DESC) as sales_rank,
    DENSE_RANK() OVER (ORDER BY total_sales DESC) as sales_category
FROM (
    SELECT 
        product_name,
        SUM(quantity * price) as total_sales
    FROM order_items oi
    JOIN products p ON oi.product_id = p.product_id
    GROUP BY product_name
) product_sales;2. Employee Performance Evaluation
-- Performance ranking by department
SELECT 
    employee_name,
    department,
    performance_score,
    RANK() OVER (
        PARTITION BY department 
        ORDER BY performance_score DESC
    ) as dept_rank,
    DENSE_RANK() OVER (
        ORDER BY performance_score DESC
    ) as company_rank
FROM employee_performance
WHERE evaluation_year = 2024;3. Sales Leaderboard
-- Monthly sales ranking
WITH monthly_sales AS (
    SELECT 
        salesperson_id,
        salesperson_name,
        SUM(sale_amount) as monthly_total
    FROM sales
    WHERE MONTH(sale_date) = MONTH(CURRENT_DATE)
    GROUP BY salesperson_id, salesperson_name
)
SELECT 
    salesperson_name,
    monthly_total,
    ROW_NUMBER() OVER (ORDER BY monthly_total DESC) as position,
    RANK() OVER (ORDER BY monthly_total DESC) as rank_with_ties,
    CASE 
        WHEN DENSE_RANK() OVER (ORDER BY monthly_total DESC) = 1 THEN 'Gold'
        WHEN DENSE_RANK() OVER (ORDER BY monthly_total DESC) = 2 THEN 'Silver'
        WHEN DENSE_RANK() OVER (ORDER BY monthly_total DESC) = 3 THEN 'Bronze'
        ELSE 'Participant'
    END as medal_category
FROM monthly_sales;When to Use Each Function
Use ROW_NUMBER() when:
- Need unique sequential numbers for each row
 - Implementing pagination
 - Breaking ties arbitrarily is acceptable
 - Creating unique identifiers for duplicate data
 
-- Pagination example
SELECT * FROM (
    SELECT 
        product_name,
        price,
        ROW_NUMBER() OVER (ORDER BY price DESC) as rn
    FROM products
) ranked
WHERE rn BETWEEN 21 AND 30;  -- Page 3 (10 items per page)Use RANK() when:
- Traditional ranking system is needed
 - Gaps after ties are acceptable/desired
 - Following sports/competition ranking conventions
 - Need to know how many items are better than current item
 
-- Olympic-style ranking
SELECT 
    athlete_name,
    score,
    RANK() OVER (ORDER BY score DESC) as olympic_rank,
    CASE 
        WHEN RANK() OVER (ORDER BY score DESC) = 1 THEN 'Gold Medal'
        WHEN RANK() OVER (ORDER BY score DESC) = 2 THEN 'Silver Medal'
        WHEN RANK() OVER (ORDER BY score DESC) = 3 THEN 'Bronze Medal'
        ELSE 'No Medal'
    END as medal
FROM competition_results;Use DENSE_RANK() when:
- Need continuous ranking without gaps
 - Categorizing into performance tiers
 - Academic grading systems
 - Want to know distinct performance levels
 
-- Academic grade categories
SELECT 
    student_name,
    final_score,
    DENSE_RANK() OVER (ORDER BY final_score DESC) as performance_level,
    CASE 
        WHEN DENSE_RANK() OVER (ORDER BY final_score DESC) <= 2 THEN 'A'
        WHEN DENSE_RANK() OVER (ORDER BY final_score DESC) <= 4 THEN 'B'
        WHEN DENSE_RANK() OVER (ORDER BY final_score DESC) <= 6 THEN 'C'
        ELSE 'D'
    END as letter_grade
FROM student_scores;Performance Considerations
-- Ensure proper indexing for ranking functions
CREATE INDEX idx_students_score ON students(score DESC);
-- Efficient ranking query
SELECT 
    name,
    score,
    RANK() OVER (ORDER BY score DESC) as rank_pos
FROM students
WHERE score >= 80;  -- Filter before ranking when possibleInterview Tips
- Remember: ROW_NUMBER() is always unique, RANK() has gaps, DENSE_RANK() has no gaps
 - Understand how each handles ties differently
 - Know when to use each function based on business requirements
 - Practice with examples that have multiple ties
 - Be able to explain the gap behavior in RANK() vs DENSE_RANK()
 
Test Your Knowledge
Take a quick quiz to test your understanding of this topic.