SQL Formatting Guide
Readable SQL takes seconds to format and saves hours in code review and incident response. Here is a pragmatic style guide for the queries you write every day.
select u.id,u.email,count(o.id) as total from users u left join orders o on o.user_id=u.id where u.active=true and u.created_at>'2024-01-01' group by u.id,u.email having count(o.id)>5 order by total desc limit 50;
SELECT u.id,
u.email,
COUNT(o.id) AS total
FROM users AS u
LEFT JOIN orders AS o
ON o.user_id = u.id
WHERE u.active = TRUE
AND u.created_at > '2024-01-01'
GROUP BY u.id,
u.email
HAVING COUNT(o.id) > 5
ORDER BY total DESC
LIMIT 50;Why Formatting Beats Cleverness
A production query lives longer than the ticket that produced it, and the person who has to debug it at 3 AM is almost never the person who wrote it. Formatting is the cheapest investment with the biggest return.
One Clause Per Line
Put each major clause (SELECT, FROM, WHERE, GROUP BY, ORDER BY, LIMIT) at the start of a line. The query's shape becomes scannable at a glance; missing joins and forgotten WHERE clauses jump out.
Uppercase Keywords
Keywords in uppercase, identifiers in lowercase. It is a 1980s habit, but it still works: your eye separates control flow from data on contrast alone. Most dialects are case-insensitive for keywords, so this is purely cosmetic — and that is the point.
Column Lists: Comma-First or Comma-Last
Pick one and stick to it. Comma-first (, column) makes it easier to add or remove the last column in a diff. Comma-last is more common and reads more naturally in English. The badchoice is both styles in the same codebase.
Alias Everything
Give every joined table a short alias (users u, orders o) and qualify every column with its alias. When a column later gets added to a joined table, you avoid "ambiguous column" errors and PR churn.
JOIN Readability
LEFT JOIN on its own line, ON indented beneath it. Multiple JOINs stack naturally and the join order becomes obvious. Prefer explicit JOINs over comma-separated FROM lists — implicit cross joins are a classic foot-gun.
WHERE Conditions
One condition per line, with AND / OR at the start of each line (not the end). It makes commenting out a condition a one-line change instead of a two-line one and keeps the operator visible on the left margin where you expect it.
Comments
Use -- … for short notes above a clause, and /* … */for anything spanning more than a line. Explain why you added a window function or picked an index hint, not what the SQL does — well-formatted SQL already shows that.
Dialect Pitfalls
- Postgres is case-sensitive for quoted identifiers;
"User"andUserare different - MySQL treats
''as a legitimate zero-length string, Postgres treats it as NULL in some contexts - SQLite stores dynamic types; a column declared INTEGER happily stores strings
- MSSQL uses
TOP n; everyone else usesLIMIT - String concatenation:
||(Postgres, SQLite),CONCAT()(MySQL/MSSQL),+(MSSQL only)
Try It
Format any query instantly with our free SQL Formatter. If you are generating INSERT statements from JSON, see the JSON → PostgreSQL tool.
One clause per line
SELECT / FROM / WHERE / GROUP / ORDER each at column zero.
Alias everything
Short table aliases save you from ambiguous-column churn later.
Operators on the left
AND/OR at the start of a line reads better and diffs cleaner.