SQL Formatting Best Practices: Write Clean Queries
Uppercase Keywords
Always write SQL keywords in uppercase. This creates a clear visual distinction between the language structure and your identifiers.
-- Bad: keywords blend with column names
select u.name, u.email, o.total
from users u
inner join orders o on u.id = o.user_id
where u.active = 1 and o.total > 50
-- Good: keywords stand out
SELECT u.name, u.email, o.total
FROM users u
INNER JOIN orders o ON u.id = o.user_id
WHERE u.active = 1 AND o.total > 50
Indentation Rules
Each clause starts on a new line. Column lists are indented. Conditions in WHERE clauses are aligned or each on their own line for complex filters.
-- Bad: everything crammed together
SELECT u.name, o.total, p.title FROM users u JOIN orders o ON u.id = o.user_id JOIN products p ON o.product_id = p.id WHERE u.active = 1 AND o.total > 50 AND p.category = 'electronics'
-- Good: one clause per line, indented columns
SELECT
u.name,
o.total,
p.title
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN products p ON o.product_id = p.id
WHERE u.active = 1
AND o.total > 50
AND p.category = 'electronics'
JOIN Formatting
Each JOIN on its own line with the join condition directly below. LEFT/RIGHT/FULL keywords make join types immediately visible.
SELECT
u.name,
o.id AS order_id,
o.total,
p.name AS product
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
AND o.status = 'completed'
INNER JOIN products p
ON p.id = o.product_id
AND p.active = 1
WHERE u.created_at > '2026-01-01'
ORDER BY o.total DESC
LIMIT 100;
Tip: When a JOIN has multiple conditions, put each on its own indented line with AND/OR at the start. This makes it easy to add or remove conditions without breaking the query.
CTE Formatting
Common Table Expressions (WITH clauses) improve readability for complex queries. Each CTE is a named, self-contained unit.
WITH active_users AS (
SELECT
id,
name,
email
FROM users
WHERE active = 1
AND last_login > CURRENT_DATE - INTERVAL '30 days'
),
user_orders AS (
SELECT
user_id,
COUNT(*) AS order_count,
SUM(total) AS lifetime_value
FROM orders
WHERE status = 'completed'
GROUP BY user_id
)
SELECT
au.name,
au.email,
uo.order_count,
uo.lifetime_value
FROM active_users au
JOIN user_orders uo ON uo.user_id = au.id
WHERE uo.order_count >= 3
ORDER BY uo.lifetime_value DESC;
Format your SQL queries automatically?
Try SQL Formatter