Use MySQL BETWEEN to select values inside an inclusive range. For a DATE column, both boundary dates are included.
SELECT id,
dt2
FROM dt_tb
WHERE dt2 BETWEEN '2005-01-01'
AND '2005-12-31'
ORDER BY dt2;
For DATETIME or TIMESTAMP columns, a half-open range is usually safer:
SELECT id,
dt
FROM dt_tb
WHERE dt >= '2005-01-01'
AND dt < '2006-01-01'
ORDER BY dt;
'2005-12-31' represents midnight at the start of December 31 when compared as a datetime. Using >= start AND < next_boundary includes every time on the final day without inventing an artificial 23:59:59 boundary.
BETWEEN includes both the lower and upper boundaries.
WHERE dt2 BETWEEN '2005-01-01'
AND '2005-12-31'
is equivalent for a DATE column to:
WHERE dt2 >= '2005-01-01'
AND dt2 <= '2005-12-31'
The original tutorial used INT(2) and zero-date defaults. Modern MySQL installations commonly use strict SQL modes, so use real date values and avoid zero dates as placeholders.
CREATE TABLE dt_tb (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
dt DATETIME NOT NULL,
dt2 DATE NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4;
INSERT INTO dt_tb (id, dt, dt2)
VALUES
(1, '2004-10-26 00:00:00', '2005-01-25'),
(2, '2004-05-05 23:56:25', '2005-06-12'),
(3, '2005-12-08 13:20:10', '2005-06-06'),
(4, '2003-05-26 00:00:00', '2007-12-18'),
(5, '2007-12-18 00:00:00', '2003-08-16');
SELECT id,
dt2
FROM dt_tb
WHERE dt2 BETWEEN '2005-01-01'
AND '2005-12-31'
ORDER BY dt2;
This returns every DATE value from January 1 through December 31, 2005, including both dates.
Suppose you want every DATETIME value in 2005. Prefer:
SELECT id,
dt
FROM dt_tb
WHERE dt >= '2005-01-01'
AND dt < '2006-01-01'
ORDER BY dt;
The exclusive upper boundary automatically includes all times on December 31, including fractional seconds if the column stores them.
The original page used YEAR(dt2) BETWEEN 2004 AND 2005:
SELECT id,
dt2
FROM dt_tb
WHERE YEAR(dt2) BETWEEN 2004 AND 2005;
This is logically correct and includes both years. When the column is indexed and you know the actual date boundaries, a direct range is usually more index-friendly:
SELECT id,
dt2
FROM dt_tb
WHERE dt2 >= '2004-01-01'
AND dt2 < '2006-01-01';
See YEAR() and year extraction.
If you intentionally want February through August from every year, extracting the month is appropriate:
SELECT id,
dt
FROM dt_tb
WHERE MONTH(dt) BETWEEN 2 AND 8
ORDER BY dt;
This matches February through August regardless of year.
See MONTH() and month extraction.
YEAR(dt) BETWEEN 2004 AND 2005 to this query means "February through August inside each of those years." It does not mean one continuous range from February 2004 through August 2005.For one continuous range, such as March 2015 through all of February 2016, use real date boundaries:
SELECT id,
dt
FROM dt_tb
WHERE dt >= '2015-03-01'
AND dt < '2016-03-01'
ORDER BY dt;
For a DATE column, the original inclusive pattern is also valid:
SELECT id,
dt2
FROM dt_tb
WHERE dt2 BETWEEN '2015-03-01'
AND LAST_DAY('2016-02-01');
See LAST_DAY().
Use CURDATE() with INTERVAL arithmetic for rolling date ranges.
For a DATE column:
SELECT id,
date
FROM dt_table
WHERE date BETWEEN CURDATE() - INTERVAL 10 DAY
AND CURDATE()
ORDER BY date;
SELECT id,
date
FROM dt_table
WHERE date BETWEEN CURDATE() - INTERVAL 1 MONTH
AND CURDATE();
SELECT id,
date
FROM dt_table
WHERE date BETWEEN CURDATE() - INTERVAL 1 YEAR
AND CURDATE();
For a DATE column:
SELECT id,
date
FROM dt_table
WHERE date BETWEEN CURDATE() - INTERVAL 6 MONTH
AND CURDATE() - INTERVAL 3 MONTH;
For DATETIME reporting buckets, decide explicitly whether touching boundaries should belong to both adjacent buckets. Half-open ranges avoid double counting at shared boundaries.
SELECT id,
date
FROM dt_table
WHERE date >= DATE_FORMAT(
CURDATE(),
'%Y-%m-01'
)
AND date < DATE_FORMAT(
CURDATE() + INTERVAL 1 MONTH,
'%Y-%m-01'
);
SELECT id,
date
FROM dt_table
WHERE date >= DATE_FORMAT(
CURDATE(),
'%Y-%m-01'
)
AND date < CURDATE() + INTERVAL 1 DAY;
The original page described first-of-month through today as "present month." The distinction matters: month-to-date stops at today, while a full-month query also covers future dates in the same month.
A simple expression is:
SELECT id,
date
FROM dt_table
WHERE YEAR(date) = YEAR(CURDATE());
For an indexed date column, prefer a direct range:
SELECT id,
date
FROM dt_table
WHERE date >= DATE_FORMAT(
CURDATE(),
'%Y-01-01'
)
AND date < DATE_FORMAT(
CURDATE() + INTERVAL 1 YEAR,
'%Y-01-01'
);
The original page used WEEKOFYEAR(date) = WEEKOFYEAR(CURDATE()) +/- 1. That can break around year boundaries. A boundary-based query is more robust.
SELECT id,
date
FROM dt_table
WHERE date >= CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY
AND date < CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY
+ INTERVAL 7 DAY;
SELECT id,
date
FROM dt_table
WHERE date >= CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY
- INTERVAL 7 DAY
AND date < CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY;
SELECT id,
date
FROM dt_table
WHERE date >= CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY
+ INTERVAL 7 DAY
AND date < CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY
+ INTERVAL 14 DAY;
WEEKDAY() returns Monday = 0 through Sunday = 6. Therefore Monday through Friday is 0 through 4.
SELECT id,
date
FROM dt_table
WHERE date >= CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY
AND date < CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY
+ INTERVAL 7 DAY
AND WEEKDAY(date) BETWEEN 0 AND 4;
WEEKDAY(date) BETWEEN 0 AND 5, which includes Saturday. Monday through Friday is 0 through 4.SELECT id,
date
FROM dt_table
WHERE date >= CURDATE() - INTERVAL WEEKDAY(CURDATE()) DAY
AND date < CURDATE() + INTERVAL 1 DAY
AND WEEKDAY(date) BETWEEN 0 AND 4;
When users select both a start date and an end date, validate the inputs and bind them as values. For a DATETIME column, convert the inclusive end date into the exclusive start of the next day.
If the user chooses:
From: 2026-09-01
To: 2026-09-09
query a DATETIME column as:
WHERE created_at >= '2026-09-01'
AND created_at < '2026-09-10'
This includes every time on September 9.
The existing Plus2net tools demonstrate building these ranges from calendar inputs:
Generate Query Using Dates from Calendar
Generate Query Using Date and Time
Not every search form needs both boundaries.
SELECT id,
created_at
FROM orders
WHERE created_at >= '2026-09-01'
ORDER BY created_at;
SELECT id,
created_at
FROM orders
WHERE created_at < '2026-09-10'
ORDER BY created_at;
If the user selected September 9 as the To date, September 10 is the exclusive boundary.
If an external value is supplied as DD-MM-YYYY, parse the expected format rather than relying on PHP to guess it.
<?php
$input='09-09-2026';
$date=DateTimeImmutable::createFromFormat(
'd-m-Y',
$input
);
if($date === false){
echo 'Invalid date.';
}else{
$mysql_date=$date->format('Y-m-d');
}
See inserting and validating date values.
For a DATETIME column and an inclusive user-selected end date:
<?php
$from=DateTimeImmutable::createFromFormat(
'Y-m-d',
'2026-09-01'
);
$to=DateTimeImmutable::createFromFormat(
'Y-m-d',
'2026-09-09'
);
if($from === false || $to === false || $from > $to){
echo 'Invalid date range.';
}else{
$start=$from->format('Y-m-d');
$end=$to->modify('+1 day')
->format('Y-m-d');
$sql="SELECT id, created_at
FROM orders
WHERE created_at >= :start
AND created_at < :end
ORDER BY created_at";
$stmt=$dbo->prepare($sql);
$stmt->bindValue(':start', $start, PDO::PARAM_STR);
$stmt->bindValue(':end', $end, PDO::PARAM_STR);
$stmt->execute();
}
Do not interpolate date strings directly into SQL. Bind them as data values.
If created_at is indexed, this form is usually easier for a normal B-tree index to use:
WHERE created_at >= '2026-09-01'
AND created_at < '2026-10-01'
than wrapping the indexed column in functions:
-- Useful for some reporting tasks, but often less index-friendly
WHERE MONTH(created_at) = 9
AND YEAR(created_at) = 2026
DATE(created_at) = ... on a large indexed DATETIME column when a direct range can express the same condition.EXPLAIN and real measurements for important production queries.BETWEEN '2026-09-01' AND '2026-09-09' does not include the whole final day for DATETIME values. Prefer an exclusive next-day boundary.
Fractional seconds can exist. The next-day exclusive boundary is simpler and safer.
First-of-month through CURDATE() stops at today. A full calendar month ends at the first day of the next month, exclusive.
Functions on the indexed column can make ordinary index use harder. Use direct boundaries when selecting one known period.
Week numbers reset at the new year. Date boundaries based on the current week's Monday are more robust.
MySQL WEEKDAY() returns Monday = 0 through Sunday = 6. Monday-Friday is 0-4, not 0-5.
Use valid dates or NULL where an absent date is allowed.
Validate the date format and bind the values with a prepared statement.
Yes. BETWEEN includes both the lower and upper boundary values.
You can, but a half-open range using >= start and < next boundary is usually safer when the user supplies date-only boundaries.
Use the start of the following day as an exclusive upper boundary instead of using the final date at midnight.
Use the first day of the current month as the inclusive start and the first day of the next month as the exclusive end.
It can return the same logical rows for that year, but a direct range such as date >= '2026-01-01' AND date < '2027-01-01' is often more index-friendly.
Use a lower-bound condition such as date_column >= :from after validating and binding the date.
WEEKDAY() returns Monday as 0, Tuesday as 1, through Sunday as 6. Monday through Friday is therefore 0 through 4.
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.
| rose | 09-06-2009 |
| I need to retrieve the records which are between the 2 days(TWO dates are of two different fields) | |
| rei | 13-07-2009 |
| I also need to get the records between dates! Is it any solution? | |
| Naveen Ram | 24-09-2009 |
| Hi, i want to select all the records which has date below 9/24/09. for eg: in datebase the records are Date 9/30/2009 9/24/2009 10/3/2009 9/26/2009 9/25/2009 in that i want to select only 9/24/09 and below. i write the query as Select Date From DateTable Where Date <= '9/24/2009'. i got result as Date 9/24/2009 10/3/2009 | |
| Girihdar | 02-10-2009 |
| hi i need the query for display the dates between the two dates, and my condition is only between dates, no retrieving the data from the database. | |
| Praise | 05-10-2009 |
| Is there a way to write this SQL code better. cos ikeep getting an error: SELECT qryViewExcesses.CIID, qryViewExcesses.CustomerName, qryViewExcesses.Industry, qryViewExcesses.RelationshipManager, qryViewExcesses.FirstDate, qryViewExcesses.DaysInExcess, qryViewExcesses.EndDate, qryViewExcesses.CCY, tbl_AllExcesses.[Date Of Report], tbl_AllExcesses.[EXCESS AMOUNT] FROM tbl_AllExcesses RIGHT JOIN qryViewExcesses ON tbl_AllExcesses.[Customer ID] = qryViewExcesses.CIID WHERE (((tbl_AllExcesses.[Date Of Report]) Between [qryViewExcesses].[FirstDate] And [qryViewExcesses].[EndDate])); | |
| Karthik | 09-10-2009 |
| hi i need the query for display the dates between the two dates, and my condition is only between dates, no retrieving the data from the database. SELECT * FROM Timesheet WHERE date BETWEEN '25/09/2009' and '07/10/2009' i didnt get any result regarding this.. pls help me to solve this problem | |
| Natalie | 03-11-2009 |
| I need to find results of a sale date that are between sysdate and 4 days from sysdate. How can I do this? | |
| smo | 04-11-2009 |
| You have to use CURDATE function, see the Must Read section at the top or visit this CURDATE | |
| Anita | 05-11-2009 |
| Hi, I want to display all the records between '2009-11-02' to '2009-11-05'. Using Between clause display dates from 2009-11-02 2009-11-03 2009-11-04 but not 2009-11-05. How can i get 2009-11-05 as well. thank you. | |
| saintjab | 24-01-2010 |
| I have two culumns date and amount. I want to find the sum between two given dates assuming table name is money. | |
| kuthey | 13-02-2010 |
| @saintjab: Dats easy. use group by | |
| vincent | 24-03-2010 |
| "Select Date From DateTable Where Date <= '9/24/2009'" use bettween.. | |
| Pattanayak | 30-03-2010 |
| Hi Anita, Please use the follwoing statement: SELECT * FROM Tablename WHERE dt BETWEEN '2009-11-02' AND '2009-11-06' thanks | |
| ankita bansal | 31-03-2010 |
| create proc SP_Get_Result ( @DateFrom nvarchar(50), @DateTo nvarchar(50) ) as SELECT * FROM Timesheet WHERE date BETWEEN @DateFrom and @DateTo i didnt get any result regarding this.. pls help me to solve this problem | |
| Big Vern | 16-04-2010 |
| I am looking to use the between dates action in Mysql, but want to use variables, so instead of SELECT * FROM Tablename WHERE date BETWEEN '2009-11-02' AND '2009-11-06' USing PHP I want to use $datefrom = date('Y-m-d',strtotime(date1)); $dateto = date('Y-m-d',strtotime(date2)); to adapt the query to SELECT * FROM Tablename WHERE date BETWEEN ".$datefrom." AND ".$dateto,"" I have tried this but it doesnt work, any ideas? | |
| Manaat | 26-04-2010 |
| i have a table in oracle where one column is xmltype and one node in the xml is date i have to write a query which selects the data from this table but between a specific date range please help | |
| kishori | 11-07-2010 |
| I have a table in mysql where one column is date and another column is medical status( FIT/Repeat ). How can I fetch the records by date and medical status. either FIT or Repeat | |
| dharma | 09-08-2010 |
| hi, i have to select the first sunday,first tuesday from date 17-8-2010 to 17-9-2010 | |
| Rik | 25-08-2010 |
| hey i am trying to use the: SELECT * FROM Tablename WHERE date BETWEEN ".$datefrom." AND ".$dateto,"" too is there any ideas to dong this ive been trying for about 2 - 3 weeks | |
| kamlesh makvana | 07-09-2010 |
| i want to display a grap of data between two date using between clause plz help me | |
| Mahesh | 14-12-2010 |
| This is Very Perfect Answer for this question | |
| Dan Lubbs | 07-11-2012 |
| ... WHERE date BETWEEN [FromDate] and [ThruDate]. Example of a FromDate is 9/1/2012 and ThruDate is 10/30/2012. I want to prompt with a normal date style not 2012-09-01. | |
| Venbha | 08-01-2013 |
| I got my need. Thank You | |
| Akhilesh | 06-08-2013 |
| I want to know the difference in the two dates. I need perfect answer using asp.net pgm sir. thank you | |
| waleed | 17-09-2013 |
| how to generate a report in php mysql. online shopping website total stock and order information . | |
| nin | 08-10-2013 |
| if i have not passed from date and to date then i want to display whole records... hows it possible | |
| Rajeev Bhatia | 30-10-2013 |
| Hi Friends, Please help me: i have a table which has a field named 'rate' and i am using between query for selecting rates and displaying records but the problem is :- how do i pass the the selected dates from two comboboxes for this i need two variables what will be the query if i have to pass variables from c# coding. Thank in advance Rajeev | |
| Swati Umakant Hingane | 01-04-2014 |
| i have table lead and i want to search record between from_date and to_date but from_date and to_date not present in database please help me........ | |
| hello there | 20-04-2014 |
| I want to display record between fromdate - todate and also between fromtime - totime. where fromtime is of fromdate and totime is of totime. like record between 01-01-2014 08:00:00 to 03-01-2014 18:00:00. in my database both field time and date are different and from where I am taking input, is a textbox. | |
| Senthil | 28-05-2014 |
| I have a two text box for from-date and to-date, in this the to-date field has an issue that the record was not fetched from the database for that to-date search, any solution for this issue | |
| Praveen | 05-06-2014 |
| Hi, I need to pass one value of date to return the entire records of that particular month of the date. Like if the date is 05-JUN-2014 I want to see the entire records of the June month..Any idea pls post back.. Thank you | |
| jaanu | 30-06-2014 |
| Hi, i need to select the date in a database in a application the application verified time is 3days if it exceeds the compensation is 50rs per exceed day i need solution for this.plzzz post back | |
| Rahul Shitole | 02-07-2014 |
| Hi, i need generate report from date wise | |
| sandeep | 16-07-2014 |
| I want to display record between fromdate - todate and also between fromtime - totime. where fromtime is of fromdate and totime is of totime. like record between 01-01-2014 08:00:00 to 03-01-2014 18:00:00. in my database both field time and date are different and from where I am taking input, is a textbox. | |
| roopa | 12-08-2014 |
| sir i got a query as below... display order info with salesman which has given on date before 10 of any month.. will pls help me in writing a sql | |
| sam | 27-08-2014 |
| 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 | |
| krishna | 14-10-2014 |
| sir i would like to retrieve data from table by using from date and to date date format is (yyyy-mm-dd hh:mm:ss) please help me | |
| ahmad | 01-12-2014 |
| i am looking to get records between to dates using vb6 coding form access table, the dates are between Apr 14 to Dec 2014 help me plz | |
| raja | 08-12-2014 |
| i am looking get records between two dates using php code dates are 01-12-2014 to 08-12-2014 please help be | |
| smo | 08-12-2014 |
| SELECT * FROM dt_table WHERE date BETWEEN '2014-12-1' AND '2014-12-8' There is a link in the tutorial to generate query by using two calendars | |
| khalid | 14-02-2015 |
| awesome man.. it solved a big prob of mine.. cheers.... wish u best of luck | |
| nthiga | 28-03-2015 |
| hi people i need to select all entries from mysql db using php where checkindate is between 1800 hrs today and 6:00hrs folowing date.The issues is if a checkin was done before 1800hrs today to tommorow 0800hrs i need to pick also this for this is between 1800hrs todays anf next day 0600 hrs how can i do this thanks allot people | |
| Maloy | 25-04-2015 |
| Hi kan somone help me to select all matches between to dates. Thanks! | |
| Patrick | 27-04-2015 |
| Try unix date format (= number of seconds counting from 01-01-1970) and add 3600 (secs) for every additional hour. '27-04-2015 18:00' = 1430085600 +(18*3600) = 1430150400 to 28-04-2015 08:00 = 1430172000 + (8*3600) = 1430200800. SELECT * FROM xtable WHERE xdate BETWEEN 1430150400 AND 1430200800. You need a xdate INT(11) column with unix time in 'xtable' for this to work | |
| Swati | 05-06-2015 |
| I want to print the details from table where date_limit(column of a table) is exceeded by 7 or more days. SELECT DATEDIFF('2014-11-30','2014-11-29') AS DiffDate is working fine but i want the following to execute I want SELECT DATEDIFF('date_limit','date_limit+7') AS DiffDate | |
| Mythili | 14-07-2015 |
| preparedStatement = connection.prepareStatement("select * from empattendance where Empid='"+select[i]+"' AND Date BETWEEN '"+fromdate+"' AND '"+todate+"'"); We need to implement for multiple employees and for dynamic dates like 20-03-2015 to 30-05-2015 | |
| kowsalya | 07-04-2016 |
| How to retrieve all the records from database where date between 2014-06-01 and 2015-05-31 database contains 12 table. | |
| smo1234 | 07-04-2016 |
| You can apply between date to each table and then use Union command to get the list. First try with each table. | |
| mwaka fred | 04-05-2016 |
| How to create queries between two different years for instance between 1950 and 1960 | |
| smo1234 | 05-05-2016 |
| SELECT * FROM `dt_tb` WHERE year( dt2 ) between 1950 and 1960 | |
| Apurba | 08-06-2016 |
| Suppose I have Year and month in two different columns, then how can I retrieve value between two dates. Thanku | |
| smo1234 | 20-06-2016 |
| select * from dt_tb where year_column='2016' and month_column='Mar' | |
| shafeeq | 28-06-2016 |
| I have a table with date stored as integer format, now i want use between operator from another application which i can give only the real date, how i can write the query for this. When i gave this query EG: Date_=27091 dbo.ConvertDateDisplay(Date_) BETWEEN'13-06-2016' and. '28-06-2016' where dbo.ConvertDateDisplay(Date_)=19-01-2015 | |
| smo1234 | 29-06-2016 |
| You can't use convertdatedisplay function here . Try with strtotime to convert the date and then compare with date between. | |
| Davide | 09-03-2017 |
| Hi smo1234, I would export all DB excluding from the dump the last 6 months, how I could do it? Many thanks! | |
| smo1234 | 12-03-2017 |
| Not much idea on this , mysqldump works in SHELL command. Another way is to use copy table with your conditions ( add 6 months date ) and then take the backup. | |
| priya | 27-06-2017 |
| I want to select from-date to-date wise data show in form plz. suggest in details code in dodeigniter | |
11-09-2019 | |
| I want to get record every 15 days Like 1-jan-2019 t0 15-jan-2019 16-jan-2019 to 30-jan-2019 in different group etc. | |
17-05-2021 | |
I want to grab data which is equal to date and between dates how can I do that? the above query works only for between dates not equal to selected dates. | |
21-06-2021 | |
| BETWEEN dates includes both ends , so it will work for equal to selected dates. If you don't want between the dates and only the ends to match then you can use like this. Date = '2021-03-27' OR Date ='2021-05-23' | |