It's 11 PM. You've been debugging a SQL query for two hours. The query is 200 lines long, all on one line, with table aliases like a1, a2, a3 that you're pretty sure stand for something meaningful but you can't remember what. Sound familiar?
I've been there. More importantly, I've been the person who wrote that query. And I've learned that good SQL formatting isn't about being neat—it's about survival.
Why Formatting Matters More Than You Think
SQL is unique among programming languages in that we read it far more than we write it. A SELECT statement might be written once but executed thousands of times, reviewed by multiple developers, and debugged at 2 AM when something breaks in production.
I've seen queries that looked correct but had subtle bugs invisible until you formatted them properly. I've also seen queries that looked like disasters but were actually correct—the formatting just made them look worse than they were.
The Basic Principles
Capitalize Keywords
This is the single biggest thing you can do to improve readability. SQL keywords (SELECT, FROM, WHERE, JOIN, etc.) should be uppercase. Everything else—table names, column names, aliases—can be lowercase. This creates visual hierarchy.
# Hard to parse
select u.name, o.total, o.date from users u join orders o on u.id = o.user_id where o.total > 100
# Easy to parse
SELECT u.name, o.total, o.date
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.total > 100
One Clause Per Line
Don't cram everything onto one line. Each major clause gets its own line. Within clauses, each condition gets its own line if it won't fit cleanly.
Align Similar Constructs
If you have multiple columns in a SELECT, align them. If you have multiple conditions in a WHERE clause, put them on separate lines and use indentation.
SELECT
u.id,
u.name,
u.email,
u.created_at,
o.order_count,
o.total_spent
FROM users u
LEFT JOIN (
SELECT user_id, COUNT(*) as order_count, SUM(total) as total_spent
FROM orders
GROUP BY user_id
) o ON u.id = o.user_id
WHERE u.status = 'active'
AND u.created_at > '2023-01-01'
AND o.total_spent > 100
JOIN Best Practices
JOINs are often where queries get messy. Here's my approach: put the JOIN keyword at the beginning of the line, indent the ON condition, and keep all the joining logic visually separated from the WHERE conditions.
Subqueries and CTEs
Modern SQL relies heavily on subqueries and Common Table Expressions (CTEs). CTEs are almost always preferable—they're more readable and easier to debug. Format them with the WITH keyword at the top, each CTE on its own line.
WITH active_users AS (
SELECT id, name, email
FROM users
WHERE status = 'active'
),
user_orders AS (
SELECT user_id, SUM(total) as total, COUNT(*) as order_count
FROM orders
GROUP BY user_id
)
SELECT
au.name,
au.email,
uo.total,
uo.order_count
FROM active_users au
JOIN user_orders uo ON au.id = uo.user_id
WHERE uo.total > 100
ORDER BY uo.total DESC
Common Mistakes
- Using SELECT * in production code—always list the columns you need
- Not using table aliases when joining multiple tables
- Forgetting to qualify column names with table aliases in joins
- Putting AND conditions before the first WHERE clause
- Not indenting subqueries