
Query to Get All Rows from the Previous Month in a Database
Last updated 2 weeks, 5 days ago | 27 views 75 5

Fetching rows from the previous month is a common requirement in reporting, analytics, and automated email summaries. Getting this right requires understanding of date functions, SQL syntax, and edge cases like year changes.
Objective
Retrieve all rows from a table where a DATE
, DATETIME
, or TIMESTAMP
column falls within the entire previous calendar month, no matter the current date.
Example Table: orders
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
customer_name VARCHAR(255),
total DECIMAL(10, 2),
order_date DATE
);
Step-by-Step SQL Query (Using MySQL)
✅ Step 1: Use CURDATE()
to Get Today's Date
SELECT CURDATE(); -- Returns current date, e.g., '2025-05-04'
✅ Step 2: Get First Day of the Previous Month
SELECT DATE_SUB(DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE()) - 1 DAY), INTERVAL 1 MONTH);
-- Example: Returns '2025-04-01'
✅ Step 3: Get First Day of the Current Month
SELECT DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE()) - 1 DAY);
-- Example: Returns '2025-05-01'
✅ Step 4: Final Query to Get All Rows from the Previous Month
SELECT *
FROM orders
WHERE order_date >= DATE_SUB(DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE()) - 1 DAY), INTERVAL 1 MONTH)
AND order_date < DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE()) - 1 DAY);
This retrieves all orders from April 1 to April 30, if today is May 4.
⌛ Using LAST_DAY()
Alternative
SELECT *
FROM orders
WHERE order_date BETWEEN
DATE_FORMAT(NOW() - INTERVAL 1 MONTH, '%Y-%m-01') AND
LAST_DAY(NOW() - INTERVAL 1 MONTH);
-
DATE_FORMAT(..., '%Y-%m-01')
: Gets the first day of the previous month. -
LAST_DAY(...)
: Gets the last day of the previous month.
✅ Full Code Example
Here’s a full working SQL snippet:
-- Create table
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
customer_name VARCHAR(255),
total DECIMAL(10,2),
order_date DATE
);
-- Insert sample data
INSERT INTO orders (customer_name, total, order_date) VALUES
('Alice', 150.00, '2025-04-05'),
('Bob', 200.00, '2025-04-20'),
('Charlie', 75.00, '2025-05-02');
-- Query all orders from the previous month
SELECT *
FROM orders
WHERE order_date BETWEEN
DATE_FORMAT(NOW() - INTERVAL 1 MONTH, '%Y-%m-01') AND
LAST_DAY(NOW() - INTERVAL 1 MONTH);
✅ Expected Output (if today is May 4): Only orders from April will be retrieved.
Tips
-
Use
BETWEEN
for Inclusive Range: It includes both start and end dates. -
Always Check Data Types: Your date column should be of
DATE
,DATETIME
, orTIMESTAMP
type. -
Be Timezone-Aware: If using
TIMESTAMP
, consider the server timezone vs user timezone. -
Use
NOW()
orCURDATE()
Consistently:NOW()
gives current date and time,CURDATE()
gives just the date.
⚠️ Common Pitfalls
-
❌ Incorrect Use of
MONTH()
/YEAR()
Only:
-- Avoid this if you care about exact boundaries
WHERE MONTH(order_date) = MONTH(CURDATE()) - 1
This breaks in January because it doesn't handle year transitions.
-
❌ Forgetting to Normalize Dates:
-
Using
NOW()
instead of stripping time portion can cause partial data to be skipped.
-
-
❌ Not Indexing Date Column:
-
Large datasets should index
order_date
for performance.
-
Bonus: Works Across Different SQL Dialects
-
✅ PostgreSQL:
SELECT * FROM orders
WHERE order_date >= date_trunc('month', CURRENT_DATE - INTERVAL '1 month')
AND order_date < date_trunc('month', CURRENT_DATE);
-
✅ SQL Server:
SELECT * FROM orders
WHERE order_date >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) - 1, 0)
AND order_date < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0);
Conclusion
Querying rows from the previous calendar month requires careful date calculation. Avoid shortcuts like subtracting 30 days, and instead rely on first day/last day logic. This makes your query resilient to month-length variations and year changes.