Calculating the difference between two dates is one of the most common tasks in database work. Whether you’re tracking project durations, finding overdue invoices, or calculating customer tenure, you need reliable ways to measure time spans. That’s where SQL DATEDIFF and date arithmetic become essential.
Date difference calculations appear everywhere in real applications: aging reports, subscription tracking, SLA monitoring, and countless business analytics scenarios. While the specific function varies between database systems, the core concept remains the same—measuring the gap between two points in time.
Throughout this guide, you’ll find interactive SQL exercises that let you practice date calculations in your browser—no database setup required. Write queries, get instant feedback, and build confidence with date arithmetic.
What is DATEDIFF?
DATEDIFF is a SQL function that calculates the difference between two dates. The exact syntax varies by database system, but the concept is universal: given two dates, return how far apart they are.
The general idea works like this:
-- Conceptual syntax (varies by database)
DATEDIFF(unit, start_date, end_date)
-- or
DATEDIFF(end_date, start_date)
Key points about date difference calculations:
- Units vary: Some databases let you specify days, months, years, hours, etc.
- Order matters: The result can be positive or negative depending on which date comes first
- Database-specific: Each database has its own syntax and functions
Date Arithmetic in Different Databases
Since DATEDIFF syntax varies significantly between databases, here’s how each major system handles it:
SQL Server
-- DATEDIFF(datepart, start_date, end_date)
SELECT DATEDIFF(day, '2024-01-01', '2024-01-15') as days_diff;
-- Returns: 14
SELECT DATEDIFF(month, '2024-01-15', '2024-06-15') as months_diff;
-- Returns: 5
MySQL
-- DATEDIFF(end_date, start_date) - returns days only
SELECT DATEDIFF('2024-01-15', '2024-01-01') as days_diff;
-- Returns: 14
-- For other units, use TIMESTAMPDIFF
SELECT TIMESTAMPDIFF(MONTH, '2024-01-15', '2024-06-15') as months_diff;
-- Returns: 5
PostgreSQL
-- Direct subtraction returns an interval
SELECT '2024-01-15'::date - '2024-01-01'::date as days_diff;
-- Returns: 14
-- Or use AGE() for detailed breakdown
SELECT AGE('2024-06-15', '2024-01-15');
-- Returns: 5 mons
SQLite
SQLite doesn’t have a built-in DATEDIFF function, but you can use Julian day calculations:
-- Subtract Julian days for date difference
SELECT julianday('2024-01-15') - julianday('2024-01-01') as days_diff;
-- Returns: 14.0
-- Cast to integer for whole days
SELECT CAST(julianday('2024-01-15') - julianday('2024-01-01') AS INTEGER);
-- Returns: 14
Basic Date Difference Calculations
Let’s start with the most common scenario: calculating the number of days between two dates.
Days Between Dates
Imagine you’re tracking order fulfillment times. You have an order date and a ship date, and need to know how long fulfillment took:
-- SQL Server
SELECT
order_id,
order_date,
ship_date,
DATEDIFF(day, order_date, ship_date) as fulfillment_days
FROM orders;
-- MySQL
SELECT
order_id,
order_date,
ship_date,
DATEDIFF(ship_date, order_date) as fulfillment_days
FROM orders;
-- SQLite
SELECT
order_id,
order_date,
ship_date,
CAST(julianday(ship_date) - julianday(order_date) AS INTEGER) as fulfillment_days
FROM orders;
Try it yourself:
[[ testData.title ]]
Query the projects table to return project_name, start_date, end_date, and calculate duration_days as the number of days between the start and end dates.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Διαθέσιμοι Πίνακες
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Finding Overdue Records
A common business requirement is finding records that have passed their due date and calculating how overdue they are.
-- Find invoices overdue as of today
-- SQL Server
SELECT
invoice_id,
due_date,
DATEDIFF(day, due_date, GETDATE()) as days_overdue
FROM invoices
WHERE due_date < GETDATE();
-- MySQL
SELECT
invoice_id,
due_date,
DATEDIFF(CURDATE(), due_date) as days_overdue
FROM invoices
WHERE due_date < CURDATE();
-- SQLite
SELECT
invoice_id,
due_date,
CAST(julianday('now') - julianday(due_date) AS INTEGER) as days_overdue
FROM invoices
WHERE due_date < date('now');
Try it yourself:
[[ testData.title ]]
Query the tasks table to find all overdue tasks (where due_date is before ‘2024-03-15’). Return task_name, due_date, and calculate days_overdue showing how many days past the deadline. Order by days overdue descending.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Διαθέσιμοι Πίνακες
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Calculating Age in Different Units
Sometimes you need the difference in months, years, or other units rather than just days.
Months Between Dates
-- SQL Server - precise months
SELECT DATEDIFF(month, '2024-01-15', '2024-06-20') as months_diff;
-- Returns: 5
-- MySQL
SELECT TIMESTAMPDIFF(MONTH, '2024-01-15', '2024-06-20') as months_diff;
-- Returns: 5
-- PostgreSQL
SELECT EXTRACT(YEAR FROM AGE('2024-06-20', '2024-01-15')) * 12 +
EXTRACT(MONTH FROM AGE('2024-06-20', '2024-01-15')) as months_diff;
-- SQLite (approximate - dividing days by 30)
SELECT CAST((julianday('2024-06-20') - julianday('2024-01-15')) / 30 AS INTEGER);
-- Returns: 5
Years Between Dates
-- SQL Server
SELECT DATEDIFF(year, '2020-03-15', '2024-06-20') as years_diff;
-- MySQL
SELECT TIMESTAMPDIFF(YEAR, '2020-03-15', '2024-06-20') as years_diff;
-- PostgreSQL
SELECT EXTRACT(YEAR FROM AGE('2024-06-20', '2020-03-15')) as years_diff;
-- SQLite (approximate)
SELECT CAST((julianday('2024-06-20') - julianday('2020-03-15')) / 365 AS INTEGER);
Try it yourself:
[[ testData.title ]]
Query the accounts table to return account_name, created_date, and calculate age_months showing how many complete months old each account is (as of ‘2024-06-01’). Order by age in months descending.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Διαθέσιμοι Πίνακες
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Working with Date Ranges
Finding records within a certain number of days from a target date is another common pattern.
-- Find all events within 7 days of a target date
-- SQL Server
SELECT event_name, event_date
FROM events
WHERE ABS(DATEDIFF(day, event_date, '2024-04-15')) <= 7;
-- MySQL
SELECT event_name, event_date
FROM events
WHERE ABS(DATEDIFF(event_date, '2024-04-15')) <= 7;
-- SQLite
SELECT event_name, event_date
FROM events
WHERE ABS(julianday(event_date) - julianday('2024-04-15')) <= 7;
Try it yourself:
[[ testData.title ]]
Query the events table to find all events that occurred within 7 days before or after ‘2024-04-15’. Return event_name, event_date, and days_from_target showing the difference (negative for before, positive for after). Order by event_date.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Διαθέσιμοι Πίνακες
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Practical Examples
Customer Tenure Analysis
Calculate how long customers have been with you:
-- SQLite example
SELECT
customer_name,
signup_date,
CAST((julianday('now') - julianday(signup_date)) / 365 AS INTEGER) as years_with_us,
CASE
WHEN julianday('now') - julianday(signup_date) < 365 THEN 'New'
WHEN julianday('now') - julianday(signup_date) < 730 THEN 'Established'
ELSE 'Loyal'
END as customer_tier
FROM customers;
SLA Monitoring
Track response times against service level agreements:
-- SQLite example
SELECT
ticket_id,
created_at,
resolved_at,
CAST(julianday(resolved_at) - julianday(created_at) AS INTEGER) as resolution_days,
CASE
WHEN julianday(resolved_at) - julianday(created_at) <= 3 THEN 'Within SLA'
ELSE 'SLA Breach'
END as sla_status
FROM support_tickets;
Subscription Renewals
Find subscriptions expiring within a certain period:
-- SQLite example - subscriptions expiring in next 30 days
SELECT
customer_name,
subscription_end,
CAST(julianday(subscription_end) - julianday('now') AS INTEGER) as days_remaining
FROM subscriptions
WHERE julianday(subscription_end) - julianday('now') BETWEEN 0 AND 30
ORDER BY days_remaining;
Common Pitfalls
NULL Date Values
Date difference calculations return NULL if either date is NULL:
-- This returns NULL, not an error
SELECT julianday(NULL) - julianday('2024-01-01');
-- Handle NULLs explicitly
SELECT COALESCE(
CAST(julianday(end_date) - julianday(start_date) AS INTEGER),
0
) as duration_days
FROM projects;
Date Format Issues
Ensure your dates are in the correct format:
-- SQLite expects ISO format: YYYY-MM-DD
-- This works:
SELECT julianday('2024-01-15');
-- This might not work as expected:
SELECT julianday('15-01-2024');
SELECT julianday('01/15/2024');
Time Component Surprises
When dates include time components, results might not match expectations:
-- These are technically 0 days apart (same calendar day)
-- but the difference includes the time component
SELECT julianday('2024-01-15 23:59:59') - julianday('2024-01-15 00:00:00');
-- Returns: ~0.999988
-- Strip time for day-only calculations
SELECT julianday(date('2024-01-15 23:59:59')) - julianday(date('2024-01-15 00:00:00'));
-- Returns: 0
Performance Tips
Index Date Columns
If you frequently filter or calculate based on dates, index those columns:
CREATE INDEX idx_orders_order_date ON orders(order_date);
CREATE INDEX idx_orders_ship_date ON orders(ship_date);
Avoid Functions in WHERE Clauses
Functions on columns prevent index usage:
-- Bad: Function on column prevents index use
SELECT * FROM orders
WHERE julianday(order_date) > julianday('2024-01-01');
-- Better: Compare directly
SELECT * FROM orders
WHERE order_date > '2024-01-01';
Pre-calculate for Reporting
For complex date calculations in reports, consider storing calculated values:
-- Add a calculated column or separate table for frequently-needed values
ALTER TABLE orders ADD COLUMN fulfillment_days INTEGER;
UPDATE orders
SET fulfillment_days = CAST(julianday(ship_date) - julianday(order_date) AS INTEGER)
WHERE ship_date IS NOT NULL;
Working with Date Calculations in Beekeeper Studio
When working with complex date calculations, a powerful SQL editor makes the difference. Beekeeper Studio provides excellent support for writing and testing date queries.
Features that help with date calculations:
- Query autocompletion: Suggests date functions as you type
- Result formatting: Displays dates in readable formats
- Multi-database support: Work with date functions across PostgreSQL, MySQL, SQLite, SQL Server, and more
- Query history: Save and reuse your date calculation patterns
The free version includes everything you need to master SQL date calculations, making it perfect for both learning and production database work.
Key Takeaways
Calculating date differences is fundamental for database work. Here’s what to remember:
- DATEDIFF syntax varies by database - learn your specific system’s approach
- SQLite uses julianday() for date arithmetic since it lacks a native DATEDIFF
- Order matters - know which date comes first to get positive or negative results
- Handle NULL values - date calculations with NULL return NULL
- Watch date formats - use ISO format (YYYY-MM-DD) for consistency
- Consider time components - use date() function when you need day-only calculations
- Index date columns - improve performance for date-based queries
- Test edge cases - leap years, month boundaries, and timezone issues can surprise you
By mastering date difference calculations, you’ll be equipped to handle aging reports, track durations, monitor deadlines, and build time-aware applications. Whether calculating customer tenure or finding overdue tasks, these techniques are essential for real-world database work.
Ready to practice more? Try the interactive examples above, or explore more SQL tutorials to continue building your database expertise.
Το Beekeeper Studio Είναι Ένα Δωρεάν & Ανοιχτού Κώδικα GUI Βάσης Δεδομένων
Το καλύτερο εργαλείο SQL query & editor που έχω χρησιμοποιήσει. Παρέχει όλα όσα χρειάζομαι για να διαχειριστώ τη βάση δεδομένων μου. - ⭐⭐⭐⭐⭐ Mit
Το Beekeeper Studio είναι γρήγορο, διαισθητικό και εύκολο στη χρήση. Το Beekeeper υποστηρίζει πολλές βάσεις δεδομένων και λειτουργεί εξαιρετικά σε Windows, Mac και Linux.
Τι Λένε Οι Χρήστες Για Το Beekeeper Studio
"Το Beekeeper Studio αντικατέστησε εντελώς την παλιά μου ροή εργασίας SQL. Είναι γρήγορο, διαισθητικό και κάνει τη δουλειά με βάσεις δεδομένων απολαυστική ξανά."
"Έχω δοκιμάσει πολλά GUIs βάσεων δεδομένων, αλλά το Beekeeper βρίσκει την τέλεια ισορροπία μεταξύ χαρακτηριστικών και απλότητας. Απλά δουλεύει."