ROW_NUMBER() in SQL

๐Ÿ”ข ROW_NUMBER() is a SQL window function that assigns a unique sequential number to each row in a result set. Numbering starts at 1 and increases by one for every row within the specified window.

๐Ÿ“– What is ROW_NUMBER()?

ROW_NUMBER() generates a unique number for each row based on the order defined in the ORDER BY clause of the OVER() window. Even if multiple rows contain identical values, each row receives a different row number.

Information

ROW_NUMBER() is commonly used for ranking, pagination, identifying duplicate rows, and selecting the first or last record within groups.

๐ŸŽฏ Why Use ROW_NUMBER()?

ROW_NUMBER() is useful whenever every row needs a unique position within a result set or partition.

  • ๐Ÿ“Œ Generate sequential row numbers.
  • ๐Ÿ“Œ Rank records uniquely.
  • ๐Ÿ“Œ Implement pagination.
  • ๐Ÿ“Œ Remove duplicate rows.
  • ๐Ÿ“Œ Select top records from each group.

๐Ÿ“‹ Sample Table

EmployeeIDEmployeeNameDepartmentSalary
101AliceSales60000
102BobSales55000
103CharlieIT75000
104DavidIT70000
105EmmaHR50000

๐Ÿ“ Basic Syntax

ROW_NUMBER() Syntax

SELECT
    column1,
    column2,
    ROW_NUMBER() OVER (
        ORDER BY column_name
    ) AS RowNum
FROM table_name;

The ORDER BY clause inside OVER() determines the sequence in which row numbers are assigned.

๐Ÿ’ก Example: Number All Employees

Assign Sequential Row Numbers

SELECT
    EmployeeName,
    Salary,
    ROW_NUMBER() OVER (
        ORDER BY Salary DESC
    ) AS RowNum
FROM Employees;

Employees are numbered from the highest salary to the lowest salary.

๐Ÿ“Š Example Output

RowNumEmployeeNameSalary
1Charlie75000
2David70000
3Alice60000
4Bob55000
5Emma50000

๐Ÿ’ก Example: Restart Numbering by Department

Use PARTITION BY to restart numbering for each group.

ROW_NUMBER() with PARTITION BY

SELECT
    EmployeeName,
    Department,
    Salary,
    ROW_NUMBER() OVER (
        PARTITION BY Department
        ORDER BY Salary DESC
    ) AS DepartmentRank
FROM Employees;

๐Ÿ“Š Example Output

EmployeeDepartmentSalaryDepartmentRank
AliceSales600001
BobSales550002
CharlieIT750001
DavidIT700002
EmmaHR500001

๐Ÿ’ก Example: Return the Highest-Paid Employee in Each Department

Top Employee per Department

SELECT *
FROM (
    SELECT
        EmployeeName,
        Department,
        Salary,
        ROW_NUMBER() OVER (
            PARTITION BY Department
            ORDER BY Salary DESC
        ) AS RowNum
    FROM Employees
) RankedEmployees
WHERE RowNum = 1;

This query returns only the highest-paid employee from each department.

๐Ÿ’ก Example: Pagination

ROW_NUMBER() is commonly used to retrieve a specific range of rows for paginated results.

Pagination Example

SELECT *
FROM (
    SELECT
        EmployeeID,
        EmployeeName,
        ROW_NUMBER() OVER (
            ORDER BY EmployeeID
        ) AS RowNum
    FROM Employees
) EmployeeList
WHERE RowNum BETWEEN 11 AND 20;

โš–๏ธ ROW_NUMBER() vs RANK() vs DENSE_RANK()

FunctionDuplicate ValuesGaps in Ranking
ROW_NUMBER()Always assigns unique numbers.Not applicable.
RANK()Same rank for ties.โœ… Yes
DENSE_RANK()Same rank for ties.โŒ No

Important

If multiple rows have identical ordering values, ROW_NUMBER()still assigns different numbers. If you need tied rows to share the same rank, use RANK() or DENSE_RANK().

๐Ÿ’ผ Real-World Applications

  • ๐Ÿ† Rank employees within each department.
  • ๐Ÿ“„ Implement paginated search results.
  • ๐Ÿ“Š Select the latest record for each customer.
  • ๐Ÿงน Remove duplicate records while keeping one row.
  • ๐Ÿ›’ Retrieve the highest-selling product in each category.

๐Ÿ—„๏ธ Database Compatibility

Database SystemROW_NUMBER() Support
MySQLโœ… Supported in MySQL 8.0 and later.
PostgreSQLโœ… Fully supported.
SQL Serverโœ… Fully supported.
Oracleโœ… Fully supported.
SQLiteโœ… Supported in SQLite 3.25.0 and later.

โš ๏ธ Common Mistakes

  • โŒ Omitting the ORDER BY clause inside OVER().
  • โŒ Assuming row numbers remain the same if the ordering changes.
  • โŒ Using ROW_NUMBER() when tied rows should share the same rank.
  • โŒ Forgetting to use PARTITION BY when numbering should restart for each group.

Warning

When the ORDER BY column contains duplicate values, ROW_NUMBER() may assign different row numbers to tied rows. To ensure consistent results, include additional columns in the ORDER BY clause to create a deterministic ordering.

โš ๏ธ Best Practices

Best Practice

Always specify a meaningful ORDER BY clause, use PARTITION BY when numbering should restart within groups, consider RANK() or DENSE_RANK() for tied rankings, and use descriptive aliases for generated row numbers to improve query readability.

๐Ÿš€ Key Points to Remember

  • ๐Ÿ“Œ ROW_NUMBER() assigns a unique sequential number to each row.
  • ๐Ÿ“Œ It is a window function and requires the OVER() clause.
  • ๐Ÿ“Œ ORDER BY determines the numbering sequence.
  • ๐Ÿ“Œ PARTITION BY restarts numbering for each group.
  • ๐Ÿ“Œ It is ideal for pagination, deduplication, and top-N queries.
  • ๐Ÿ“Œ Unlike RANK(), duplicate values never share the same row number.
>>"ROW_NUMBER() gives every row a unique place in line, even when values are identical."

Summary

โœ… ROW_NUMBER() is a powerful SQL window function that assigns a unique sequential number to every row based on a specified ordering. It is widely used for pagination, ranking, selecting top records within groups, and removing duplicates while preserving complete row-level detail.