Introduction
Working with databases often requires a firm handle on querying techniques, especially when it comes to finding records within a specific date range. In this guide, you’ll learn how to use MySQL to select rows that fall between two dates or times—a common task for any data professional.
We’ll start with the fundamentals before moving on to more complex queries. By the end, you should feel comfortable crafting SQL queries for a variety of situations that require selecting rows based on dates and times.
Basic Time Range Selection
Let’s begin with the basics of selecting rows where a date column is between two dates. Imagine you have a table orders
with a purchase_date
field. The query looks something like this:
SELECT * FROM orders
WHERE purchase_date BETWEEN '2021-01-01' AND '2021-01-31';
In the above SQL, the BETWEEN
operator is used to retrieve rows with purchase_date
between two specified dates. This includes the boundaries—rows from January 1st, 2021 and January 31st, 2021, are included.
Handling Time Components
Sometimes your date columns will include times as well. To select rows within the exact time range, specify the time:
SELECT * FROM orders
WHERE purchase_date BETWEEN '2021-01-01 00:00:00' AND '2021-01-01 23:59:59';
In this instance, only rows from the very beginning of January 1st, 2021 up to just before the start of January 2nd are selected. This includes the entire first day up to the last second.
Using TIMESTAMP and DATETIME Types
If your dates are stored as TIMESTAMP
or DATETIME
types in MySQL, you handle these just like a date. Let’s assume you have a table events
with a datetime_field
:
SELECT * FROM events
WHERE datetime_field BETWEEN '2023-03-12 08:00:00' AND '2023-03-14 17:00:00';
This will return all events happening from March 12th, 2023, 8 AM to March 14th, 2023, 5 PM.
Dealing with TimeZone
TimeZone can affect your queries. MySQL stores TIMESTAMP
in UTC by default. A common practice is converting it back to your local timezone:
SELECT *, CONVERT_TZ(purchase_date, '+00:00', 'SYSTEM') as local_purchase_date
FROM orders
WHERE CONVERT_TZ(purchase_date, '+00:00', 'SYSTEM') BETWEEN '2021-01-01 09:00:00' AND '2021-01-31 17:00:00';
Advanced Queries with Aggregate Functions
Often, you’ll want to combine date range selections with aggregate functions to summarize data. Here’s how you might get a count of orders per day in January 2021:
SELECT DATE(purchase_date) AS order_date, COUNT(*) as total_orders
FROM orders
WHERE purchase_date BETWEEN '2021-01-01' AND '2021-01-31'
GROUP BY order_date;
Indexing and Performance
Selecting rows between dates can be efficient if you have an index on the date column. Without it, these queries may suffer from performance issues because of full table scans.
Subqueries and JOIN Operations
For more complexed reports, you might need to filter a join operation with a date constraint. Let’s say you want to get all orders with products that have been on discount during the order’s date:
SELECT o.id, o.purchase_date, p.product_name
FROM orders o
JOIN products p ON o.product_id = p.id
JOIN discounts d ON p.id = d.product_id
WHERE o.purchase_date BETWEEN d.start_date AND d.end_date;
This joins the orders
table with products
and discounts
and selects the rows where the order’s date falls within the discount period of the product.
Handling NULL Dates
What if some rows have NULL in date columns? The BETWEEN
operator ignores these rows. Sometimes it’s essential to handle NULL
dates intentionally:
SELECT * FROM orders
WHERE (purchase_date IS NULL OR purchase_date BETWEEN '2021-01-01' AND '2021-01-31');
Always make sure to escape your date values to prevent SQL injection attacks when working with user-provided dates. Use prepared statements or libraries that handle this.
Conclusion
Selecting rows between specific dates and times in MySQL can be accomplished with ease, provided you understand the basic SQL syntax and the nuances of date and time types. Practicing the above techniques will uplift your Data Management skills, guiding you towards mastering the manipulation and eager grasp of temporal data.