SQL Formatting Best Practices
SQL is one of those languages where formatting dramatically impacts readability. A 200-line query can be either a nightmare or perfectly clear depending on how it's laid out.
The Problem
This is what most SQL looks like in the wild:
SELECT u.id, u.name, u.email, COUNT(o.id) as order_count, SUM(o.total) as total_spent FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE u.created_at > '2025-01-01' AND u.status = 'active' GROUP BY u.id, u.name, u.email HAVING COUNT(o.id) > 0 ORDER BY total_spent DESC LIMIT 50;Now properly formatted:
SELECT
u.id,
u.name,
u.email,
COUNT(o.id) AS order_count,
SUM(o.total) AS total_spent
FROM users u
LEFT JOIN orders o
ON u.id = o.user_id
WHERE u.created_at > '2025-01-01'
AND u.status = 'active'
GROUP BY u.id, u.name, u.email
HAVING COUNT(o.id) > 0
ORDER BY total_spent DESC
LIMIT 50;Rule 1: One Clause Per Line
Each major SQL clause (SELECT, FROM, WHERE, GROUP BY, ORDER BY) gets its own line. This makes it trivial to scan the query structure.
Rule 2: Leading Commas vs Trailing Commas
Trailing (standard):
SELECT
id,
name,
emailLeading (easier to comment out):
SELECT
id
, name
, emailLeading commas make it easier to comment out columns during debugging. Both are valid — pick one and be consistent.
Rule 3: Indent Join Conditions
FROM users u
LEFT JOIN orders o
ON u.id = o.user_id
AND o.status = 'completed'
INNER JOIN products p
ON o.product_id = p.idThe ON clause indented under the JOIN makes the relationship instantly clear.
Rule 4: Uppercase Keywords
SELECT, FROM, WHERE, JOIN, AND, OR — uppercase SQL keywords visually separate them from column/table names. This is the most universally accepted SQL convention.
Rule 5: Meaningful Aliases
Bad: FROM users a JOIN orders b
Good: FROM users u JOIN orders o
Better: FROM users usr JOIN orders ord
Single-letter aliases work for simple queries. For complex queries with 5+ tables, use 2-3 letter abbreviations.
CTEs Over Subqueries
Instead of nested subqueries:
WITH active_users AS (
SELECT id, name
FROM users
WHERE status = 'active'
),
recent_orders AS (
SELECT user_id, SUM(total) AS total_spent
FROM orders
WHERE created_at > '2025-01-01'
GROUP BY user_id
)
SELECT
au.name,
ro.total_spent
FROM active_users au
JOIN recent_orders ro
ON au.id = ro.user_id
ORDER BY ro.total_spent DESC;CTEs (Common Table Expressions) break complex queries into named, readable chunks. Each CTE is a self-contained unit you can test independently.
Automatic Formatting
Don't format SQL by hand. Use a formatter that applies these rules consistently. The key is that everyone on the team uses the same one.
Try it now: Format your SQL queries instantly — paste messy SQL, get clean output.