MAX() – Find the Maximum Value in a Column in MySQL

The MySQL MAX() function is an aggregate function that returns the maximum value from an expression.

Typically, the expression would be a range of values returned as separate rows in a column, and you can use this function to find the maximum value from the returned rows. If there are no matching rows, MAX() returns NULL.

For example, you can use this function to find out which city has the largest population out of a list of cities.

Syntax

The syntax of MAX() goes like this:

MAX([DISTINCT] expr) [over_clause]

Where expr is the expression for which you want the maximum value.

The over_clause is an optional clause that works with window functions. Note that the over_clause can only be used if you don’t use the DISTINCT keyword.

The (optional) DISTINCT keyword can be used to eliminate duplicate values.

Basic Example

First, here’s the raw data that we’ll use in this example:

USE world;
SELECT Name, Population
FROM City
WHERE CountryCode = 'THA';

Result:

+-------------------+------------+
| Name              | Population |
+-------------------+------------+
| Bangkok           |    6320174 |
| Nonthaburi        |     292100 |
| Nakhon Ratchasima |     181400 |
| Chiang Mai        |     171100 |
| Udon Thani        |     158100 |
| Hat Yai           |     148632 |
| Khon Kaen         |     126500 |
| Pak Kret          |     126055 |
| Nakhon Sawan      |     123800 |
| Ubon Ratchathani  |     116300 |
| Songkhla          |      94900 |
| Nakhon Pathom     |      94100 |
+-------------------+------------+

We can use the MAX() function to find the city with the largest population (i.e. the row with the maximum value in its population column).

USE world;
SELECT MAX(Population) AS 'Maximum Value'
FROM City
WHERE CountryCode = 'THA';

Result:

+---------------+
| Maximum Value |
+---------------+
|       6320174 |
+---------------+

The GROUP BY Clause

We can use the GROUP BY clause to list out each country, along with the population of that country’s largest city (by population):

USE world;
SELECT District, MAX(Population) AS 'Max Value'
FROM City
WHERE CountryCode = 'AUS'
GROUP BY District;

Result:

+-----------------+-----------+
| District        | Max Value |
+-----------------+-----------+
| New South Wales |   3276207 |
| Victoria        |   2865329 |
| Queensland      |   1291117 |
| West Australia  |   1096829 |
| South Australia |    978100 |
| Capital Region  |    322723 |
| Tasmania        |    126118 |
+-----------------+-----------+

The ORDER BY Clause

We can also use the ORDER BY clause to specify a column with which to order by:

USE world;
SELECT District, MAX(Population) AS 'Max Value'
FROM City
WHERE CountryCode = 'AUS'
GROUP BY District
ORDER BY `Max Value` ASC;

Result:

+-----------------+-----------+
| District        | Max Value |
+-----------------+-----------+
| Tasmania        |    126118 |
| Capital Region  |    322723 |
| South Australia |    978100 |
| West Australia  |   1096829 |
| Queensland      |   1291117 |
| Victoria        |   2865329 |
| New South Wales |   3276207 |
+-----------------+-----------+

This orders the results in ascending order, which lists the minimum value first.

Note that, when ordering by a multi-word alias (like `Max Value`), you need to use the backtick character (`) instead of the apostrophe (') to surround the two words.

Find the Maximum Character Length

The MAX() function isn’t limited to just columns with numerical data. You can also combine MAX() with other functions to return maximum values in other areas.

For example, using our sample data, we can find the value with the maximum number of characters in the City column:

SELECT MAX(CHAR_LENGTH(Name)) AS 'Maximum Character Length'
FROM city;

Result:

+--------------------------+
| Maximum Character Length |
+--------------------------+
|                       34 |
+--------------------------+

We can also see this by using the following query (which doesn’t involve the MAX() function):

SELECT Name, CHAR_LENGTH(Name) AS 'Character Length'
FROM city
ORDER BY `Character Length` DESC
LIMIT 10;

Result:

+--------------------------------------+------------------+
| Name                                 | Character Length |
+--------------------------------------+------------------+
| Luxembourg [Luxemburg/Lëtzebuerg]   |               34 |
| Castellón de la Plana [Castell      |               31 |
| San Fernando del Valle de Cata       |               30 |
| Santo Domingo de los Colorados       |               30 |
| Thiruvananthapuram (Trivandrum       |               30 |
| [San Cristóbal de] la Laguna        |               29 |
| Ingraj Bazar (English Bazar)         |               28 |
| Soledad de Graciano Sánchez         |               28 |
| Valle de Chalco Solidaridad          |               27 |
| Machilipatnam (Masulipatam)          |               27 |
+--------------------------------------+------------------+

Using an OVER Clause

As mentioned, the syntax allows for an OVER clause to be included in your queries. Basically, the OVER clause allows you to specify how to partition query rows into groups for processing by the window function.

Here’s an example:

SELECT 
    District,
    Name AS City,
    Population AS 'City Population',
    MAX(Population) OVER(PARTITION BY District) AS 'District Max'
FROM City
WHERE CountryCode = 'AUS'
ORDER BY `District Max` DESC;

Result:

+-----------------+---------------+-----------------+--------------+
| District        | City          | City Population | District Max |
+-----------------+---------------+-----------------+--------------+
| New South Wales | Sydney        |         3276207 |      3276207 |
| New South Wales | Wollongong    |          219761 |      3276207 |
| New South Wales | Newcastle     |          270324 |      3276207 |
| New South Wales | Central Coast |          227657 |      3276207 |
| Victoria        | Melbourne     |         2865329 |      2865329 |
| Victoria        | Geelong       |          125382 |      2865329 |
| Queensland      | Townsville    |          109914 |      1291117 |
| Queensland      | Brisbane      |         1291117 |      1291117 |
| Queensland      | Cairns        |           92273 |      1291117 |
| Queensland      | Gold Coast    |          311932 |      1291117 |
| West Australia  | Perth         |         1096829 |      1096829 |
| South Australia | Adelaide      |          978100 |       978100 |
| Capital Region  | Canberra      |          322723 |       322723 |
| Tasmania        | Hobart        |          126118 |       126118 |
+-----------------+---------------+-----------------+--------------+

This example partitions the rows by District, providing the maximum value for each partition (district). This allows you to see more granular data, such as each city’s population, along with the population of the largest city in the same district.