Selecting the Row with the Maximum Value in SQL: Techniques, Examples, and Best Practices
When working with relational databases, a common requirement is to retrieve the entire row that holds the highest (or lowest) value for a particular column. Whether you need the most recent order, the highest‑paid employee, or the product with the greatest stock level, SQL offers several reliable patterns to achieve this goal. This guide walks through the most widely used methods, explains when each is appropriate, and provides concrete examples for MySQL, PostgreSQL, SQL Server, and Oracle. By the end, you’ll be able to choose the approach that balances readability, performance, and portability for your specific use case Practical, not theoretical..
Why Simply Using MAX() Isn’t Enough
The aggregate function MAX(column) returns the highest value, but it discards the rest of the row. That said, most real‑world queries demand the accompanying columns—such as the employee name, order date, or product description—associated with that maximum. Because of that, if you only need the value itself, MAX is sufficient. To obtain the full row, you must combine MAX with a join, a subquery, or a window function The details matter here..
Method 1: Subquery with MAX()
A correlated or non‑correlated subquery that computes the maximum value and then filters the main table is the most portable solution. It works across all major RDBMS because it relies only on standard SQL Worth knowing..
Syntax
SELECT *
FROM your_table t
WHERE t.target_column = (
SELECT MAX(target_column)
FROM your_table
);
When to Use
- The table is modest in size (up to a few hundred thousand rows).
- You need a solution that runs on any SQL dialect without extensions.
- Simplicity and readability outweigh micro‑optimizations.
Example (MySQL)
SELECT e.employee_id, e.first_name, e.last_name, e.salary
FROM employees e
WHERE e.salary = (
SELECT MAX(salary)
FROM employees
);
If multiple employees share the top salary, the query returns all of them—a useful side effect when ties matter.
Method 2: Join with a Derived Table
Instead of a correlated subquery, you can compute the maximum in a derived table (or CTE) and join it back to the original table. This often allows the optimizer to evaluate the aggregate once and reuse it The details matter here..
Syntax
SELECT t.*
FROM your_table t
JOIN (SELECT MAX(target_column) AS max_val
FROM your_table) m
ON t.target_column = m.max_val;
When to Use
- You prefer explicit joins over nested subqueries.
- The database optimizer tends to materialize derived tables efficiently (common in PostgreSQL and SQL Server).
- You anticipate adding more aggregate columns (e.g., both
MAXandMIN) in the same query.
Example (PostgreSQL)
WITH max_salary AS (
SELECT MAX(salary) AS max_sal
FROM employees
)
SELECT e.employee_id, e.first_name, e.last_name, e.salary
FROM employees e
JOIN max_salary ms ON e.salary = ms.max_sal;
Method 3: ORDER BY … LIMIT 1 (or FETCH FIRST)
If you are certain that only one row should be returned—even when ties exist, you accept an arbitrary pick—sorting descending and limiting the result set is concise and often fast, especially when an index exists on the sorted column.
Syntax (MySQL, PostgreSQL, SQLite)
SELECT *
FROM your_table
ORDER BY target_column DESC
LIMIT 1;
Syntax (SQL Server 2012+)
SELECT TOP 1 *
FROM your_table
ORDER BY target_column DESC;
Syntax (Oracle 12c+)
SELECT *
FROM your_table
ORDER BY target_column DESC
FETCH FIRST 1 ROW ONLY;
When to Use
- You need a single row and are indifferent to ties.
- An index on
target_columnlets the database fetch the first entry without a full table scan. - Simplicity is essential and you are working with a dialect that supports
LIMIT/FETCH.
Caveat
If the column contains NULL values, they appear last in ascending order and first in descending order depending on the DBMS’s null‑sorting behavior. Add WHERE target_column IS NOT NULL if you want to ignore nulls.
Method 4: Window Functions (ROW_NUMBER, RANK, DENSE_RANK)
Modern SQL provides analytic functions that let you rank rows within partitions. By assigning a rank of 1 to the maximum value(s), you can filter the result set in a single pass. This method shines when you need the maximum per group (e.Here's the thing — g. , highest salary per department) or when you want to keep ties explicitly.
Syntax
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (ORDER BY target_column DESC) AS rn
FROM your_table
) ranked
WHERE rn = 1;
Replace ROW_NUMBER with RANK or DENSE_RANK if you want all rows that share the maximum value to appear (RANK gives identical ranks for ties, leaving gaps; DENSE_RANK gives consecutive ranks).
When to Use
- You need the maximum within groups (
PARTITION BY). - You want to keep ties (
RANK/DENSE_RANK) or arbitrarily pick one (ROW_NUMBER). - You are already using window functions for other calculations, making this a natural extension.
Example (SQL Server – highest salary per department)
SELECT employee_id, first_name, last_name, salary, department_id
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY department_id
ORDER BY salary DESC) AS rn
FROM employees
) ranked
WHERE rn = 1;
Performance Note
Window functions require a sort operation. If an index exists on the ordering column(s), the engine can often avoid a separate sort, making this method competitive with the subquery approach That's the part that actually makes a difference..
Method 5: QUALIFY Clause (Snowflake, BigQuery)
Some newer data warehouses support the QUALIFY clause, which filters the result of a window function directly, eliminating the need for a subquery or CTE.
Syntax (Snowflake)
SELECT *
FROM your_table
QUALIFY ROW_NUMBER() OVER (ORDER BY target_column DESC) = 1;
When to Use
- You are working in Snowflake, Google BigQuery, or another platform that implements
QUALIFY. - You prefer a linear, readable flow without nesting.