How do you handle dates in SQL?
Truncate, extract, date math, the monthly report skeleton, month-over-month growth with LAG, and the timestamp traps: every SQL date pattern you keep googling, on one printable page.
Get the free PDF
One page, print-ready, free to share. No signup needed.
Time breaks every query eventually: two date formats, a timezone, a BETWEEN that quietly drops the last day. Here is every date pattern you keep googling, on one page. The print-ready A4 PDF is at the bottom.
Truncate
DATE_TRUNC('month', d): first of the month, the backbone of every report.DATE_TRUNC('week', d): Monday.ts::DATE: drop the time part.
Parts and labels
EXTRACT(dow FROM d): day of week, 0 = Sunday.EXTRACT(hour FROM ts): for hourly heatmaps.TO_CHAR(d, 'YYYY-MM'): month labels for humans; store dates, format at the end.
Date math
d + INTERVAL '1 month': add.d2 - d1: days between.NOW() - INTERVAL '30 day': the rolling window.AGE(d2, d1): gap in years/months/days.
The monthly report, complete
WITH m AS (
SELECT DATE_TRUNC('month', d) AS mo,
SUM(rev) AS rev
FROM sales GROUP BY 1)
SELECT mo, rev,
ROUND(100.0 * (rev / LAG(rev)
OVER (ORDER BY mo) - 1), 1) AS mom
FROM m ORDER BY mo;
LAG reads the previous row of the ordered result: last month, no self-join. The same shape gives running totals (SUM() OVER (ORDER BY d)) and 7-day moving averages (ROWS 6 PRECEDING).
The traps: timestamps end at midnight
| You wrote | What happens | Write instead |
|---|---|---|
BETWEEN '08-01' AND '08-31' | drops Aug 31 after 00:00 | >= '08-01' AND < '09-01' |
WHERE ts::DATE = CURRENT_DATE | index unused, full scan | range on the raw ts |
GROUP BY day, no series | empty days just vanish | generate_series + LEFT JOIN |
And two habits that prevent the rest: store timestamps in UTC (AT TIME ZONE 'UTC') and convert at display time; treat '1970-01-01' as what it usually is, a fake null wearing a date costume.
Frequently asked questions
How do I group by month in SQL?
How do I compute month-over-month growth in SQL?
Why does BETWEEN miss rows on the last day of the month?
Why do missing days disappear from my daily report?
Get the free PDF
One page, print-ready, free to share. No signup needed.