Hook: Interviewers love MAX because it looks tiny, but it checks whether you understand aggregation, NULL handling, and how SQL finds “the biggest” value.
Question: What does MAX do in SQL?
Answer: MAX returns the largest value in a column or expression. It is an aggregate function, which means it combines many rows into one result, and it ignores NULL values. You can use it with numbers, dates, and often text, depending on the database’s sorting rules.
Interview-Ready Answer: MAX is an aggregate function that returns the highest non-NULL value in a set of rows. I use it when I want the latest date, highest price, or top score, and if all rows are NULL it returns NULL. One detail I always remember is that it can also work per group with GROUP BY, so I can get the maximum for each department, customer, or day.
MAX isDetailed Explanation: Think of MAX as a “keep the best so far” function. As rows flow through the query, SQL compares each value with the current winner and keeps the larger one. That makes it an aggregate function: many input rows, one output value per group.
GROUP BY group.NULL value becomes the current maximum.Important: NULL means “unknown/missing,” not “smallest.” So MAX skips NULL values entirely. If every value in the set is NULL, the result is NULL.
| Approach | What it returns | Typical use |
|---|---|---|
MAX(col) | One value | Highest value only |
ORDER BY col DESC LIMIT 1 | One row | Need the row itself |
MAX(col) OVER (...) | Value per row | Compare each row to a max |
When to use which: If you only need the largest value, MAX is the cleanest choice. If you need the whole row that owns that value, you usually need sorting, a window function, or a join back to the max result.
In the simplest case, MAX scans the rows once, so the time cost is O(n) for each group and the extra memory is usually O(1). In real databases, an index on the target column can make things faster: many engines can jump to the end of a b-tree index and read the highest value quickly. That is an optimizer improvement, not a promise of the SQL language, so you should think of MAX as logically scanning all rows unless the engine proves otherwise.
NULL: result is NULL.NULL.MAX still returns one value; it does not tell you which row it came from.Memory Hook: Picture a scoreboard: every new row challenges the current champion, and MAX keeps only the best score on the board.
Real-World Story: In a checkout service for an e-commerce app, the team wants the highest order total per customer to flag VIP buyers. They run MAX(order_total) grouped by customer_id to find the largest purchase amount. That number feeds a loyalty dashboard and a fraud rule that watches for unusually large transactions.
What goes wrong when someone misunderstands MAX? A developer may assume it returns the latest row, not just the largest value. Then they write code that shows the biggest payment amount but pairs it with the wrong order ID, causing support to email the wrong customer. In logs, you might see mismatched IDs and totals, and users notice weird VIP badges or incorrect alerts. The fix is to separate “find the max value” from “find the row that owns it.”
-- Demonstrates MAX as an aggregate, grouped MAX, and an edge case with all-NULL values.
-- This is standard SQL style using a VALUES table expression.
WITH sales(dept, employee, salary) AS (
SELECT *
FROM (VALUES
('Sales', 'Ava', 90000),
('Sales', 'Ben', 95000),
('Sales', 'Cara', NULL),
('Engineering', 'Dev', 120000),
('Engineering', 'Eli', 115000),
('HR', 'Hana', 70000),
('Interns', 'Ian', NULL),
('Interns', 'Ivy', NULL)
) AS t(dept, employee, salary)
)
-- 1) Highest salary per department.
SELECT
dept,
MAX(salary) AS max_salary
FROM sales
GROUP BY dept
ORDER BY dept;
-- 2) Overall maximum salary.
-- MAX ignores NULLs, so only real salary values can win.
SELECT MAX(salary) AS overall_max_salary
FROM sales;
-- 3) Edge case: all rows in a group are NULL.
-- MAX returns NULL, so COALESCE is only safe when you truly want a fallback.
SELECT
dept,
MAX(salary) AS raw_max_salary,
COALESCE(MAX(salary), 0) AS fallback_salary
FROM sales
WHERE dept = 'Interns'
GROUP BY dept;Follow-up & Tricky Questions:
MAX handle NULL? It ignores NULL values. If every value is NULL or the set is empty, the result is NULL.MAX work with dates? Yes. For dates and timestamps, it returns the latest value, which is often very useful for “most recent activity” queries.MAX(col) and ORDER BY col DESC LIMIT 1? MAX returns one value, while ORDER BY ... LIMIT 1 returns a full row. Use MAX when you only need the value; use ordering when you need the row itself.MAX be used as a window function? Yes. With OVER, it gives the maximum over a moving partition while still returning one result per row, which is useful for comparisons and running analytics.MAX return 0 for an empty table? No. Aggregate MAX returns NULL when there are no non-NULL values to compare.MAX the same as “last inserted row”? No. It is based on value order, not insertion order. The newest inserted row may have a smaller value than older rows.MAX tell you which row won? No. It only returns the winning value, not the row identity. If you need the row, you must query differently.Common Mistakes:
MAX returns a row. Correction: it returns a single value, so use a join or ranking when you need the full row.NULL counts as the smallest value. Correction: MAX ignores NULL entirely.MAX for “latest inserted”. Correction: “latest” by insert time needs a timestamp column, not the aggregate itself.Memory Hook: “MAX = keep the champion.” Every new row is a challenger; the current best survives unless the challenger is bigger.
Cheat Sheet:
MAX returns the largest non-NULL value.OVER, as a window function.O(n); memory is usually O(1).NULL for empty/all-NULL input.Practice Tasks:
salary in an employees table.department and return the max salary per department.created_at timestamp for each customer, then think about how you would also fetch the matching order row.