MySQL DATE_FORMAT() to PostgreSQL TO_CHAR() in Real Queries
DATE_FORMAT() and TO_CHAR() both work for grouping and display in PostgreSQL, but neither lets a plain index satisfy a query that filters or groups by the formatted string — the query-shape implications matter more than the syntax swap.
Close equivalent Covers the common case, but has documented behavioral differences.
- MySQL feature
DATE_FORMAT()- PostgreSQL equivalent
TO_CHAR()
Main limitation: Grouping by a formatted string (`GROUP BY DATE_FORMAT(created_at, '%Y-%m')`) works in both engines, but neither can use a plain index on `created_at` to satisfy that GROUP BY — both need a functional/expression index on the formatted expression itself to avoid a full scan at scale.
Quick mapping
| MySQL | DATE_FORMAT() |
|---|---|
| PostgreSQL | TO_CHAR() |
Examples
Filtering by formatted month in a WHERE clause (anti-pattern in both)
SELECT * FROM orders WHERE DATE_FORMAT(created_at, '%Y-%m') = '2026-07'; SELECT * FROM orders WHERE TO_CHAR(created_at, 'YYYY-MM') = '2026-07'; Grouping report rows by formatted month
SELECT DATE_FORMAT(created_at, '%Y-%m') AS month, COUNT(*) FROM orders GROUP BY month; SELECT TO_CHAR(created_at, 'YYYY-MM') AS month, COUNT(*) FROM orders GROUP BY month; Caveats
Caveat
Grouping by a formatted string (GROUP BY DATE_FORMAT(created_at, '%Y-%m')) works in both engines, but neither can use a plain index on created_at to satisfy that GROUP BY — both need a functional/expression index on the formatted expression itself to avoid a full scan at scale.
Caveat
TO_CHAR()'s return type is always text; DATE_FORMAT()'s return type is a string in MySQL's connection charset. Comparing or sorting the formatted output as if it preserved chronological order is unsafe in both engines once the format string reorders date components (e.g. day before year).
Caveat
For the token-by-token format-string syntax differences between DATE_FORMAT() and TO_CHAR() (which specifier maps to which), see the dedicated date-format converter linked below — it is unit-tested against every supported format token, which this crosswalk page intentionally does not duplicate.
References
- MySQL Reference Manual — DATE_FORMAT() (v8.4) — checked 2026-07-29
- PostgreSQL docs — to_char (v17) — checked 2026-07-29
Last verified 2026-07-29.