The SQL BETWEEN operator filters values within an inclusive range. Both boundary values are included.
SELECT id, name, class, mark
FROM student
WHERE mark BETWEEN 60 AND 75;
This is equivalent to:
SELECT id, name, class, mark
FROM student
WHERE mark >= 60
AND mark <= 75;
For the Plus2net sample student table, marks of exactly 60 and 75 are included.
SELECT column_list
FROM table_name
WHERE column_name BETWEEN lower_value AND upper_value;
The values are compared according to the datatype and comparison rules of the expression.
This query includes marks equal to 60 and 75:
SELECT id, name, mark
FROM student
WHERE mark BETWEEN 60 AND 75
ORDER BY mark ASC, id ASC;
| id | name | class | mark |
|---|---|---|---|
| 4 | Krish Star | Four | 60 |
| 5 | John Mike | Four | 60 |
| 20 | Jackly | Nine | 65 |
| 21 | Babby John | Four | 69 |
| 34 | Gain Toe | Seven | 69 |
| 1 | John Deo | Four | 75 |
| 18 | Honny | Five | 75 |
In normal MySQL BETWEEN usage, the first boundary should be the lower value and the second should be the upper value.
SELECT id, name, mark
FROM student
WHERE mark BETWEEN 75 AND 60;
This is a valid query, but for ordinary numeric data it returns no rows because no value can be both greater than or equal to 75 and less than or equal to 60.
NOT BETWEEN returns values outside the inclusive range.
SELECT id, name, mark
FROM student
WHERE mark NOT BETWEEN 50 AND 100;
Because BETWEEN includes the boundaries, NOT BETWEEN means:
WHERE mark < 50
OR mark > 100
BETWEEN filters the rows; ORDER BY controls how those rows are displayed.
SELECT id, name, class, mark
FROM student
WHERE mark BETWEEN 60 AND 75
ORDER BY mark DESC, id ASC;
This displays the filtered marks from highest to lowest.
Restrict the range to class Four:
SELECT id, name, class, mark
FROM student
WHERE mark BETWEEN 60 AND 75
AND class = 'Four'
ORDER BY mark ASC, id ASC;
See AND / OR conditions for combining filters.
Keep only classes Four and Seven:
SELECT id, name, class, mark
FROM student
WHERE mark BETWEEN 60 AND 75
AND class IN (
'Four',
'Seven'
);
Exclude those classes:
SELECT id, name, class, mark
FROM student
WHERE mark BETWEEN 60 AND 75
AND class NOT IN (
'Four',
'Seven'
);
See SQL IN and NOT IN for membership conditions and NULL cautions.
Use COUNT() when only the number of matching rows is required:
SELECT COUNT(*) AS total_students
FROM student
WHERE mark BETWEEN 60 AND 75;
Combine BETWEEN with GROUP BY to count matching students in each class:
SELECT class,
COUNT(*) AS total_students
FROM student
WHERE mark BETWEEN 60 AND 75
GROUP BY class
ORDER BY class;
| class | total_students |
|---|---|
| Five | 1 |
| Four | 4 |
| Nine | 1 |
| Seven | 1 |
MySQL conditional aggregation can classify ranges:
SELECT class,
SUM(
CASE WHEN mark < 50
THEN 1 ELSE 0 END
) AS grade_C,
SUM(
CASE WHEN mark BETWEEN 50 AND 70
THEN 1 ELSE 0 END
) AS grade_B,
SUM(
CASE WHEN mark > 70
THEN 1 ELSE 0 END
) AS grade_A
FROM student
GROUP BY class;
This version uses CASE, which is clearer and more portable than relying on MySQL's IF() for the same conditional-count idea.
BETWEEN works naturally with columns stored as SQL DATE values:
SELECT id, event_date, title
FROM events
WHERE event_date BETWEEN
'2026-09-01'
AND
'2026-09-30'
ORDER BY event_date;
Because DATE values contain no time component, both September 1 and September 30 are fully included.
Selecting Records between Two DatesBe careful when a column contains a time component.
This query:
SELECT id, created_at
FROM orders
WHERE created_at BETWEEN
'2026-09-01'
AND
'2026-09-30';
treats the upper literal as the start of September 30 when converted to a datetime value. Records later during September 30 can therefore be missed.
For a complete month range, a half-open interval is often safer:
SELECT id, created_at
FROM orders
WHERE created_at >= '2026-09-01 00:00:00'
AND created_at < '2026-10-01 00:00:00';
BETWEEN can compare text values too, but the result follows the database's string comparison and collation rules.
SELECT id, name
FROM student
WHERE name BETWEEN
'A'
AND
'M'
ORDER BY name;
For alphabetic range requirements, understand the active collation because case, accents and character ordering can affect comparisons.
If the tested value or a boundary is NULL, the comparison normally evaluates as unknown rather than true.
SELECT id, name, mark
FROM student3
WHERE mark BETWEEN 50 AND 75;
Rows where mark is NULL are not returned. See SQL NULL values.
When range boundaries come from a form or application, validate them and bind them as values.
<?php
require 'config.php';
$minimum=60;
$maximum=75;
if($minimum > $maximum){
[$minimum,$maximum]=[$maximum,$minimum];
}
$stmt=$dbo->prepare(
"SELECT id,name,class,mark
FROM student
WHERE mark BETWEEN :minimum AND :maximum
ORDER BY mark ASC, id ASC"
);
$stmt->bindValue(
':minimum',
$minimum,
PDO::PARAM_INT
);
$stmt->bindValue(
':maximum',
$maximum,
PDO::PARAM_INT
);
$stmt->execute();
while($row=$stmt->fetch(PDO::FETCH_ASSOC)){
echo htmlspecialchars(
(string)$row['name'],
ENT_QUOTES,
'Windows-1252'
).' : '.
(int)$row['mark'].
'<br>';
}
The SQL remains the same whether it is executed from PHP, Python or another database client. The application layer is responsible for validating and supplying the range values safely.
EXPLAIN when a production range query is unexpectedly slow.BETWEEN is inclusive. BETWEEN 60 AND 75 includes both 60 and 75.
A reversed ordinary range is valid SQL but usually returns no matching values. Normalize user-entered boundaries when necessary.
A date such as '2026-09-30' does not automatically mean every time on that day. For whole periods, a half-open range ending at the next period boundary is often safer.
BETWEEN filters by actual values. LIMIT restricts how many result rows are returned.
NULL represents an unknown value and does not evaluate as true in an ordinary BETWEEN comparison.
When boundaries come from an application, validate them and use prepared-statement parameters.
Yes. BETWEEN includes both the lower and upper boundary values.
It is equivalent to a condition requiring the value to be greater than or equal to 60 and less than or equal to 75.
The SQL is valid, but an ordinary numeric range such as BETWEEN 75 AND 60 normally returns no rows because the lower and upper conditions cannot both be satisfied.
Yes. It works well with DATE values, but DATETIME or TIMESTAMP columns require care because a date-only upper boundary can exclude later times on the final day.
NOT BETWEEN returns values outside the inclusive range.
No ordinary range match is true when the tested value is NULL because the comparison evaluates as unknown.
Validate the lower and upper values, normalize their order if needed, and bind each boundary as a prepared-statement parameter.
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.
| Sajib | 31-03-2010 |
| thanks. this is very helpful... | |
| alan | 08-11-2010 |
| so how would you have just the marks for id 4 and 5 display? | |
| Bas | 14-01-2011 |
| SELECT * FROM `student` WHERE id=4 OR id=5 | |
| keerthana | 14-09-2011 |
| hi.. i need a mysql query for selecting transactions between two dates | |
| Sam in Kenya | 25-09-2011 |
| Hie keerthana: SELECT date from jobvacancies WHERE `date` BETWEEN DATE_SUB( CURDATE( ) ,INTERVAL 12 MONTH ) AND DATE_SUB( CURDATE( ) ,INTERVAL 3 MONTH) | |
| mebrahtu | 28-11-2011 |
| I have read (the SQL BETWEEN Command to fetch records from a range ) above. And it was very informative and helpful.thanks for who posted it. | |
| rasheed | 12-01-2012 |
| i need a query of sql to get ten top student from table on base of their marks plz help any one | |
| Jone | 18-01-2012 |
| @rasheed: SELECT * FROM Students ORDER BY Marks DESC LIMIT 10 | |
| Azim | 20-02-2012 |
| how to use BETWEEN command using upper limit and lower limit exclusive | |
| reno rey quiza | 03-10-2012 |
| thanks a lot... this is really helpful... ! may you be returned a favor.. :)) | |
| naveen | 27-10-2012 |
| i want only 50% marks in sql query | |
| PRAMOD | 01-01-2013 |
| TWO TABLES ARE GIVEN ,EMPLOYEES AND DEPARTMENT . DISPLAY THE NAMES OF ALL THE EMPLOYEES WHOSE SALARY IS NOT WITHIN THE RANGE FOR THE CORRESPONDING DEPARTMENT | |
| mahamad | 26-03-2013 |
| i want to do pagination in jsp so how i will be able to do that?plz help me ... | |
| Coder | 29-08-2013 |
| i want to get the supplier details from a table named supplier by giving supplier code and between two dates also without supplier code | |
| smo | 30-08-2013 |
| SELECT * FROM `supplier_table` WHERE dt BETWEEN 2005-01-01 AND 2005-12-31 and supplier_id=1234 You can read more on query using two date ranges here. | |
| Priya | 15-07-2014 |
| I need a query which will select only those data whose length of data is within 10 to 12 and those length is greater or equal to 10, should start with 91 or 0 | |
| omkar | 10-12-2014 |
| I need a query to count duplicate data between two dates. | |
| ravi | 25-02-2015 |
| i need to display three columns as name,count(range 5-10),count(range 6-10), the source table contain two columns i.e name and range example name range aaaa 5 bbbb 9 aaaa 6 aaaa 7 bbbb 9 aaaa 5 and i need output as name count(range 0-5) count(range 6-10 ) aaaa 2 2 bbbb 0 2 | |
| Yusuf Ibrahim | 04-05-2015 |
| Please I need help in php and mysql, a code that will automatically generates position for a students according to their total marks.thank | |
| Chandu | 26-06-2015 |
| How to select only those rows whose sex is male....? | |
| smo1234 | 27-06-2015 |
| You can use Order by to list students according to their mark. | |
| SHIV PANKAJ | 23-02-2016 |
| I have a table having record in one column like "2016-01-02 19:45:31.000". I have to select record with time between 19:40 and 19:50 for whole month. Kindly provide me the query....... | |
| chandu | 03-03-2016 |
| hi i need a query to fetch records for every 6 hrs interval in a day i.e., 4 times a day from a table | |
| smo1234 | 10-08-2018 |
| Query using different time along with date like records between 9 to 18 hours of a particular date , all records with time 10 to 12 hours , all records group by hour etc are explained at DATE_SUB() and BETWEEN queries here. | |
09-01-2023 | |
| Informative ,thanks | |