Physical Address
Haryana ,India
Physical Address
Haryana ,India
In the SQL world, especially in MySQL, window functions are powerful tools for analytics. Among these, RANK(), DENSE_RANK(), and ROW_NUMBER() are three commonly used functions to assign rankings to rows. But they don’t behave the same way — and picking the wrong one can mess up your results.
Let’s break them down so you know exactly when to use each.
Ranking functions in MySQL let you assign a position number to rows within a group, based on the order you define. They’re essential in analytics — from creating leaderboards to analyzing sales performance trends.
They work with the OVER() clause, which defines:
Each row in a partition is given a rank using RANK(); however, if two or more rows have the same value, they share the same rank. The next rank gets skipped.
Syntax:
RANK() OVER (PARTITION BY column ORDER BY column)
RANK() Example
Dataset:
Player | Score |
A | 100 |
B | 90 |
C | 90 |
D | 80 |
Query:
SELECT
Player,
Score,
RANK() OVER (ORDER BY Score DESC) AS rank_position
FROM scores;
Output:
Player | Score | rank_position |
A | 100 | 1 |
B | 90 | 2 |
C | 90 | 2 |
D | 80 | 4 |
Key point: Notice rank 3 is missing — because RANK() skips numbers after ties.
DENSE_RANK() works like RANK() but does not skip numbers after ties. This makes it “dense” — no gaps in ranking.
Syntax:
DENSE_RANK() OVER (PARTITION BY column ORDER BY column)
DENSE_RANK() Example
Using the same dataset:
Query:
SELECT
Player,
Score,
DENSE_RANK() OVER (ORDER BY Score DESC) AS dense_rank_position
FROM scores;
Output:
Player | Score | dense_rank_position |
A | 100 | 1 |
B | 90 | 2 |
C | 90 | 2 |
D | 80 | 3 |
Key point: No missing numbers — ties still share the same rank.
ROW_NUMBER() simply gives each row a unique number, even if the values are tied.
Syntax:
ROW_NUMBER() OVER (PARTITION BY column ORDER BY column)
ROW_NUMBER() Example
Query:
SELECT
Player,
Score,
ROW_NUMBER() OVER (ORDER BY Score DESC) AS row_num
FROM scores;
Output:
Player | Score | row_num |
A | 100 | 1 |
B | 90 | 2 |
C | 90 | 3 |
D | 80 | 4 |
Key point: Every row gets a distinct number — ties don’t matter.
Key Differences Between RANK(), DENSE_RANK(), and ROW_NUMBER()
Feature | RANK() | DENSE_RANK() | ROW_NUMBER() |
Handles Ties | Yes | Yes | No |
Skips Numbers | Yes | No | No |
Unique Numbers | No | No | Yes |
Use Case | Leaderboards with gaps | Compact rankings | Sequential numbering |
RANK(), DENSE_RANK(), and ROW_NUMBER() might seem similar at first glance, but their subtle differences can make or break your query logic. Choose based on whether you care about ties, gaps in numbering, or unique sequence assignment.
By mastering these functions, you’ll handle leaderboards, reports, and data cleanup with confidence.
Q1: Which is faster, RANK() or ROW_NUMBER()?
A1: Performance is usually similar, but indexing can make ROW_NUMBER() slightly faster in large datasets.
Q2: Can I use these functions without PARTITION BY?
A2: Yes, PARTITION BY is optional. Without it, the ranking applies to the entire result set.
Q3: Does MySQL support NTILE()?
A3: Yes, it does, and it divides data into equal groups — different from ranking.
Q4: How do I reset ranking for each category?
A4: In the OVER() clause, use PARTITION BY category_column.
Q5: Can these be used in UPDATE queries?
A5: Yes, but you must use them in a subquery or CTE first.