MySQL - Get row number on select
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Getting a row number in MySQL depends on which version you are using and what kind of numbering you actually need. In modern MySQL, the clean solution is the ROW_NUMBER() window function. In older MySQL versions, developers often used session variables as a workaround, but that approach is less robust and should be treated as a legacy technique.
Use ROW_NUMBER() in Modern MySQL
If you are on MySQL 8.0 or newer, use the window function directly.
This assigns row numbers according to the ORDER BY inside the window definition. That ordering is crucial, because row numbers without a defined order are not meaningful.
If you want row numbers within groups, add PARTITION BY.
That restarts numbering inside each department.
Understand What the Number Means
A row number is not a stored property of the table. It is a value computed for the result set you are asking for.
That means if the ordering changes, the row number changes too. This is why ROW_NUMBER() is often used for:
- ranked reports
- paging and slicing
- top-n-per-group queries
- deterministic presentation order
It should not be confused with a persistent ID column.
Legacy MySQL Used Session Variables
Before window functions were available, a common workaround used a session variable.
This often works in simple cases, but it is more fragile than the window-function approach. It depends on execution details and is best treated as a compatibility technique for old systems rather than as the preferred modern pattern.
If you are maintaining an older codebase, it may still be the only option, but new code should use ROW_NUMBER() where possible.
Use Row Numbers for Pagination Carefully
A row number can help build result slices.
This is easy to read, but it is not always the fastest pagination strategy for very large datasets. For high-volume APIs, keyset pagination is often a better design than deep offset-style numbering.
So the right question is not only "can I number the rows" but also "is numbered pagination the query pattern I really want?"
Ordering and Indexing Still Matter
ROW_NUMBER() does not remove the cost of sorting. If you number rows by a column with poor indexing or huge cardinality, the query may still be expensive.
That is why window functions solve the expression problem more than the performance problem. The database still needs to evaluate the requested order.
Common Pitfalls
The most common mistake is asking for row numbers without defining a meaningful order. Another is treating the row number as if it were a stable table identity instead of a value derived from the query result.
Developers maintaining older MySQL versions also often rely on session-variable numbering without realizing it is a workaround rather than a first-class feature.
Finally, row-number pagination can be convenient but not always the best scaling strategy. If the result set is large and the query is latency-sensitive, revisit the access pattern, not just the SQL syntax.
Summary
- In MySQL 8.0 and newer, use
ROW_NUMBER()for row numbering. - Always define the numbering order explicitly.
- Use
PARTITION BYwhen numbering should restart within groups. - Session variables are a legacy workaround for older MySQL versions.
- Row numbers are computed result-set values, not permanent row identities.

