MySQL MAX() returns the highest non-NULL value produced by an expression. It can be used with numbers, dates, and text values.
SELECT MAX(mark) AS max_mark
FROM student;
For the sample rows below, the highest mark is 85.
SELECT MAX(expression)
FROM table_name;
MAX() ignores NULL values. If no non-NULL value is available, the aggregate result is NULL.
The first examples use these rows from the student table:
| id | name | class | mark |
|---|---|---|---|
| 1 | John Deo | Four | 75 |
| 2 | Max Ruin | Three | 85 |
| 3 | Arnold | Three | 55 |
| 4 | Krish Star | Four | 60 |
| 5 | John Mike | Four | 60 |
| 6 | Alex John | Four | 55 |
SELECT MAX(mark) AS max_mark
FROM student;
| max_mark |
|---|
| 85 |
The alias max_mark gives the aggregate result a useful column name.
This is a common requirement: find the highest mark and also return the student who has that mark.
Do not write:
-- Wrong or invalid for this purpose
SELECT id,
name,
class,
MAX(mark) AS max_mark
FROM student;
With ONLY_FULL_GROUP_BY enabled, MySQL rejects this because the non-aggregate columns are not grouped. With permissive settings, those columns can come from an arbitrary row and are not guaranteed to belong to the maximum mark.
Use a subquery instead:
SELECT id,
name,
class,
mark
FROM student
WHERE mark = (
SELECT MAX(mark)
FROM student
);
This returns every student whose mark equals the maximum value.
If the requirement is specifically to return only one highest row, sort and limit the result:
SELECT id,
name,
class,
mark
FROM student
ORDER BY mark DESC, id
LIMIT 1;
The secondary id sort provides deterministic tie-breaking. See top and second-highest value examples.
A subquery using WHERE mark = (SELECT MAX(mark) ...) returns all ties.
For example, if two students both have mark 96:
SELECT id,
name,
mark
FROM student
WHERE mark = (
SELECT MAX(mark)
FROM student
)
ORDER BY id;
Both rows are returned. This is usually preferable when "all students with the highest mark" is the real requirement.
Use GROUP BY to calculate the maximum for each class:
SELECT class,
MAX(mark) AS max_mark
FROM student
GROUP BY class
ORDER BY class;
| class | max_mark |
|---|---|
| Four | 75 |
| Three | 85 |
This query returns the maximum mark for each group, but it still does not identify the full student row that produced each maximum.
To return the student rows that contain each class maximum, first calculate the maximum for each class and then join those results back to the source table:
SELECT s.id,
s.name,
s.class,
s.mark
FROM student AS s
JOIN (
SELECT class,
MAX(mark) AS max_mark
FROM student
GROUP BY class
) AS m
ON m.class = s.class
AND m.max_mark = s.mark
ORDER BY s.class, s.id;
This correctly returns ties as separate rows when two students share the highest mark in the same class.
With MySQL 8.0+, RANK() provides another clear solution:
WITH ranked AS (
SELECT id,
name,
class,
mark,
RANK() OVER (
PARTITION BY class
ORDER BY mark DESC
) AS rnk
FROM student
)
SELECT id,
name,
class,
mark
FROM ranked
WHERE rnk = 1
ORDER BY class, id;
RANK() keeps tied highest rows. Use ROW_NUMBER() instead only when the requirement is exactly one row per group and you have defined a deliberate tie-breaker.
A WHERE clause filters the rows before MAX() is calculated.
SELECT MAX(mark) AS max_mark
FROM student
WHERE class = 'Four';
For the sample table, the maximum mark in class Four is 75.
If you select class as well, group by it:
SELECT class,
MAX(mark) AS max_mark
FROM student
WHERE class = 'Four'
GROUP BY class;
When data comes from related tables, aggregate only the columns that belong to the grouping logic. Do not select an unrelated product column beside MAX(qty) unless the query also identifies which row produced that maximum.
For example, find the maximum quantity recorded for each store:
SELECT a.store,
MAX(a.qty) AS max_qty
FROM sales AS a
GROUP BY a.store
ORDER BY a.store;
If you then need the matching product row and its price, calculate the maximum by store first and join back to sales, followed by the product table:
SELECT s.store,
s.qty AS max_qty,
p.product,
p.price,
p.price * s.qty AS total_price
FROM sales AS s
JOIN (
SELECT store,
MAX(qty) AS max_qty
FROM sales
GROUP BY store
) AS m
ON m.store = s.store
AND m.max_qty = s.qty
LEFT JOIN products AS p
ON p.p_id = s.p_id
ORDER BY s.store, s.p_id;
This avoids the old pattern of grouping only by store while selecting a product that is not functionally tied to the aggregate result.
Products and sales JOIN exampleGROUP BY collapses multiple source rows into one result row per group. A window-function form of MAX() keeps each detail row while adding the group maximum beside it:
SELECT id,
name,
class,
mark,
MAX(mark) OVER (
PARTITION BY class
) AS class_max
FROM student
ORDER BY class, id;
This is useful for reports that need both the original row and the class maximum. See the existing OVER() and PARTITION BY tutorial.
MAX() can also operate on character columns. MySQL compares text according to the column's collation.
SELECT MAX(name) AS max_name
FROM student;
This returns the greatest text value according to the active collation. It is not a numeric comparison and should not be described simply as "the highest alphabet."
If numbers are stored as text, MAX() compares the text representation rather than the numeric value.
For these VARCHAR values:
'1', '2', '3', '4', '5', '6', '12', '13'
a text comparison can produce 6 as the maximum because the values are compared lexically.
Convert the values to a numeric type before taking the maximum:
SELECT MAX(
CONVERT(t1, UNSIGNED)
) AS numeric_max
FROM max_value;
The result is 13.
Sample table:
CREATE TABLE max_value (
t1 VARCHAR(2) NOT NULL
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4;
INSERT INTO max_value
(t1)
VALUES
('1'),
('2'),
('3'),
('4'),
('5'),
('6'),
('12'),
('13');
See MySQL CONVERT() for more conversion examples.
On a DATE or DATETIME column, MAX() returns the latest non-NULL date/time value.
SELECT MAX(exam_dt) AS latest_exam
FROM student_mark;
When the table can contain more than one year, grouping only by month number mixes January from different years. Group by both year and month:
SELECT YEAR(exam_dt) AS exam_year,
MONTH(exam_dt) AS exam_month,
MAX(exam_dt) AS latest_exam
FROM student_mark
GROUP BY YEAR(exam_dt),
MONTH(exam_dt)
ORDER BY exam_year, exam_month;
Download the existing student_mark sample SQL data.
MAX() ignores NULL values. If every selected value is NULL, or no rows satisfy the filter, the result is NULL.
SELECT MAX(mark) AS max_mark
FROM student
WHERE id > 1000;
If the application needs a fallback value, use COALESCE() only when that fallback has a correct business meaning:
SELECT COALESCE(
MAX(mark),
0
) AS max_mark
FROM student
WHERE id > 1000;
You can create a new table containing the row or rows with the maximum mark:
CREATE TABLE student_max AS
SELECT id,
name,
class,
mark
FROM student
WHERE mark = (
SELECT MAX(mark)
FROM student
);
CREATE TABLE ... AS SELECT copies the selected data and derives column definitions, but it does not reproduce all indexes, constraints, AUTO_INCREMENT properties, triggers, or other table attributes from the source table.If you need a new table with the source table's structure first, use:
CREATE TABLE student_max
LIKE student;
INSERT INTO student_max
(id, name, class, mark)
SELECT id,
name,
class,
mark
FROM student
WHERE mark = (
SELECT MAX(mark)
FROM student
);
If the destination table already exists, use an INSERT ... SELECT approach.
After connecting to MySQL with PDO, a static grouped MAX query can be executed with query():
<?php
$sql="SELECT class,
MAX(mark) AS max_mark
FROM student
GROUP BY class
ORDER BY class";
$stmt=$dbo->query($sql);
foreach($stmt as $row){
echo '<p>'
.htmlspecialchars(
$row['class'],
ENT_QUOTES,
'Windows-1252'
)
.' : '
.htmlspecialchars(
(string)$row['max_mark'],
ENT_QUOTES,
'Windows-1252'
)
.'</p>';
}
This query contains no external values, so query() is appropriate. When the class or another condition comes from user input, use a prepared statement and bind the value.
MAX(indexed_column) query can often benefit from an appropriate index, depending on the filter, table structure, and optimizer plan.YEAR(date_col) and MONTH(date_col) can require more work than grouping by a stored/indexed reporting key on very large tables.EXPLAIN and real query measurements for performance decisions rather than assuming every MAX query requires a special optimization.SELECT name, MAX(mark) FROM student does not reliably return the name belonging to the highest mark. Use a subquery, JOIN, or window function.
A maximum value can belong to more than one row. Decide whether the requirement is to return every tied row or exactly one row with an explicit tie-breaker.
GROUP BY MONTH(exam_dt) combines the same month from different years. Include the year when the data spans multiple years.
VARCHAR values are compared as text. Store numeric data in a numeric datatype whenever practical.
It does not preserve all indexes, constraints, AUTO_INCREMENT properties, triggers, and other source-table attributes.
Do not use MAX(id) as an insert-ID mechanism. Another connection may insert a newer row. Use LAST_INSERT_ID() or the database API's insert-ID feature.
Download the full Plus2net student table SQL dump
MAX() returns the highest non-NULL value produced by the selected expression.
Compare the column with a subquery such as WHERE mark = (SELECT MAX(mark) FROM student), or use a JOIN or window function.
A subquery that compares the column with MAX() returns all matching ties. ORDER BY with LIMIT 1 returns only one row according to the specified tie-breaker.
Use MAX() with GROUP BY, for example SELECT class, MAX(mark) FROM student GROUP BY class.
Yes. NULL values are ignored. If there is no non-NULL value to evaluate, the result is NULL.
Yes. On DATE or DATETIME values, MAX() returns the latest non-NULL date or time.
VARCHAR values are compared as text rather than as numbers. Use a numeric column type, or convert the text to a numeric type before applying MAX().
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.
| alper | 05-06-2009 |
| very productive examples. it teaching GROUP BY statement by one example. thank you for your post. | |
| David Koh | 15-06-2009 |
| Another way to get the whole row where max_mark is the highest. Instead of the below from the example: SELECT * FROM `student` WHERE mark=(select max(mark) from student) We can do: SELECT * FROM `student` ORDER BY max_mark DESC LIMIT 1 This might save db processing power instead of having 2 select statements | |
| smo | 17-06-2009 |
| This is explained here in getting highest number by using limit | |
| rammohan | 26-06-2009 |
| how to get the last entry in pages in a table | |
| ajay | 30-07-2009 |
| how to get name of topper of every class | |
| super | 10-08-2009 |
| What if you had two or three top students (say arnold got 85 as well), how would you display the name of all of them with there mark? | |
| smo | 11-08-2009 |
| You can display top 3 by using order by and limit command. Here is the sql to display top three records. | |
| arcavalierenero | 12-09-2009 |
| This sample isn't correct: SELECT id,name,class,MAX(mark) as max_mark FROM `student` | |
| smo | 12-09-2009 |
| Yes, you are right. To display matching records we have to use subquery. The content is modified with the above explanation. | |
| Doug M | 15-09-2009 |
| I got a complex array I need to build from SQL. Using a theory like this, how could I retrieve the top 3 scores per game from a highscores table? Got a mod I am working on where people are asking that. I am hoping there is a simple SQL solution rather than building a complex array. | |
| smo | 17-09-2009 |
| you can use limit and order by to get top 3 records. | |
| karthi | 06-01-2010 |
| how to display first 2 toppers in the class? any idea.. | |
| piyush | 15-04-2010 |
| I wanted to know how to find the max salary between two table pl tell me | |
| rakesh7434 | 07-05-2010 |
| i have a table with some data i need to reproduce with same data and add new cols to it how to do it please tell me | |
| Babs | 18-05-2010 |
| how do i pick the data with the highest currency from dis data? name itemdesc tamt smith longe 450 smith longe 470 | |
| sai | 01-07-2010 |
| how to return a zero value if selected value of max(columnname) doesnot exist. | |
| manmohan | 29-07-2010 |
| How to get result like this id name class mark 1 John Deo Four 75 2 Max Ruin Three 85 display max marks in each class with its other associated fields | |
| dbl | 03-08-2010 |
| @manmohan something along the lines of select * from table group by class order by mark asc should do what you want | |
| Atef | 03-10-2010 |
| how do i select the max ID value from table and insert this value in other ID record which in other table | |
| anji | 04-10-2010 |
| I need max value ( in emp_city)in the below talbe emp_name Emp_id Emp_city abc 12 cc01 bbc 13 cc02 abc 12 cc01 agc 15 cc03 dbc 16 cc01 Result cc01 How can i get this one?please tell me anyone? | |
| DARSHAN BHAWSAR | 08-11-2010 |
| I need an SQL to get the last updated transaction on the basis of date. eg. Date Remarks 13/09/10 a 13/10/10 b SQL should return value as b since it is last updated transaction. | |
| satish.s | 02-05-2011 |
| Dear Sir/madam, We r dong project on vb with oledb conn with msaccess 2003 how to fetch maximum value of msaccess field to vb 6.0 please send us select statement of this query please do needfull Regards Satish.S | |
| zorrs | 20-05-2011 |
| how to select the row/field base on the latest date | |
| sadia | 02-06-2011 |
| i want to find sum of maximum marks of a student.e.g student got subject A = gpa 2.5 subject B= gpa 3 subject A= gpa 2 (reappeared) subjct A= gpa 3.5 (reappeared) sum of gpa= 3+3.5 what would be the query for it? | |
| sanzoO | 07-10-2011 |
| There is table say tbl_data which have the folling data id, user_name, mark1, mark2, mark3, mark4 ...... what ll be the query for finding the name of 3rd heighest scrorer Help me out... | |
| some12die4 | 17-02-2012 |
| Anoher simple way is just to use order and limit like this: SELECT xx,xx2 FROM students ORDER BY mark DESC LIMIT 1 | |
| Bim | 17-02-2012 |
| @sanzoO
select * from `tbl_data` ORDER BY `mark1`+`mark2`+`mark3`+`mark4` DESC LIMIT 2,1; @zorrs & @DARSHAN BHAWSAR have to be more specific, group by `id` ORDER BY max(`latestdate`) DESC ? @anji SELECT * FROM `table` ORDER BY `Emp_id` DESC LIMIT 1; | |
| vinoth | 12-09-2012 |
| i have tried to be in inner join Based,Find Max Value
The Query Is: select Last(b.ProgramName),RDate,ValidDate, OfferOpenDate,Last(c.OfferID) from tblStudentReg as a left outer join (tblOfferProgram as b left outer join tblOfferScheme as c on b.OfferID=c.OfferID)on a.ProgramName=b.ProgramName where RegistrationNO=1 group by RDate,ValidDate,OfferOpenDate | |
| arlene ballada | 08-11-2012 |
| how to get the largest average balance in Sql....can you help? | |
| vishakha gupta | 16-04-2014 |
| Hi, i wanna know that on selecting any value in my form then retreving the data only some value from my table within my database on the basis of matching the starting string i.e. "CA-1" in php then how can i do this? please ans. | |
| Sirjiskit | 06-05-2014 |
| How will I find the position of students in examination from the average | |
| Vijay Sharma | 07-07-2014 |
| hello,tell me that how i fine the second largest salary in a emp table. | |
| vijay | 23-08-2014 |
| i have a table that table name is student how i get max(mark) in max(Id) and min(mark) in min(Id) in singl tbl? | |
| rakesh chand | 30-01-2015 |
| very very Thank you for this tutorial. | |
| prameela | 16-03-2015 |
| we have a two tables mid1,mid2, by using that we sholud get the best of the two. | |
| Ujjwal Kumar | 09-11-2015 |
| I am trying the fetch the biggest value from any where in database table sql query but I am unable to do so please if anybody know please share query??? | |
| L.Sankaranarayanan | 14-11-2015 |
| SELECT id,name,class,MAX(mark) as max_mark FROM `student` didn't work in my h2 An error message showing 'group by ' necessary after stuent | |
| Deepak | 06-06-2016 |
| level_type = 1; i want to get all maximum maximum value where level_type='1'; like a example user1=50; user2 = 80; user3 = 100; user4=10; then result should be = 100,80,50,10.. thanks in advance ...sorry for weak english | |
| smo1234 | 20-06-2016 |
| For this you need Order by Query | |
| jyoti | 13-07-2016 |
| I am trying the fetch the biggest value from any where in database table sql query but I am unable to do so please if anybody know please share query?....... | |
| khenu | 08-04-2017 |
| i am trying to get the maximum value for this list of numbers 0,1,2,3,4,5,10,12,13,14,15 using SELECT MAX(column-name) table-name would give a result of 5 and not 15. Why? | |
| smo1234 | 10-04-2017 |
| It is considering the data as chars and first character is used for ranking, Now the highest first char is 5 , so it is returning 5 as maximum value. You need to convert the data to integer first and then apply MAX query. This part is added now. If all your data is integer then you can change the column type to Integer and they try MAX command | |
| yagnesh patel | 23-11-2018 |
| I want to result in mysql query as given max times stored value in table e.g. id name 1 a 2 b 3 c 4 a 5 a so it should come "a" | |
| smo1234 | 25-11-2018 |
| You can use ORDER BY with LIMIT query. | |
| Edward | 19-04-2019 |
| Very useful article....its has explained very clearly why data was not returning properly from my query as one of the number fields in my database column was formatted a VARCHAR,therefore trying to return a max() on this field was returning the wrong figure. The explanation offered is brilliant ! Thank you | |