Unformatted SQL is one of the biggest causes of bugs in database-heavy applications. A query that was readable when first written becomes unmaintainable after three months of changes. SQL formatting is not optional — it is part of writing professional database code.
Before and After: The Impact of Formatting
SQL
-- ❌ Unreadable (real code seen in production)
SELECT u.id,u.name,u.email,COUNT(o.id) as orders,SUM(o.total) as revenue FROM users u LEFT JOIN orders o ON u.id=o.user_id WHERE u.created_at>'2024-01-01' AND u.status='active' GROUP BY u.id,u.name,u.email HAVING COUNT(o.id)>0 ORDER BY revenue DESC LIMIT 20SQL
-- ✅ Formatted and readable
SELECT
u.id,
u.name,
u.email,
COUNT(o.id) AS orders,
SUM(o.total) AS revenue
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE
u.created_at > '2024-01-01'
AND u.status = 'active'
GROUP BY
u.id, u.name, u.email
HAVING COUNT(o.id) > 0
ORDER BY revenue DESC
LIMIT 20SQL Formatting Rules
- Keywords in UPPERCASE — SELECT, FROM, WHERE, JOIN, GROUP BY, HAVING, ORDER BY
- One clause per line — each major clause starts a new line
- Indent column lists — each selected column on its own indented line
- Align AS keywords — vertically align aliases for readability
- Explicit JOIN types — write LEFT JOIN not just JOIN
- Table aliases — use meaningful short aliases (u for users, o for orders)
- Parentheses for complex conditions — never guess operator precedence
Formatting Complex WHERE Clauses
SQL
-- ❌ Hard to read conditions
WHERE status='active' AND (role='admin' OR role='editor') AND created_at>'2024-01-01' AND NOT deleted
-- ✅ Each condition on its own line
WHERE
status = 'active'
AND (
role = 'admin'
OR role = 'editor'
)
AND created_at > '2024-01-01'
AND NOT deletedFormatting CTEs (Common Table Expressions)
SQL
WITH monthly_revenue AS (
SELECT
DATE_TRUNC('month', created_at) AS month,
SUM(total) AS revenue
FROM orders
WHERE status = 'completed'
GROUP BY 1
),
top_customers AS (
SELECT
user_id,
SUM(total) AS lifetime_value
FROM orders
GROUP BY user_id
HAVING SUM(total) > 1000
)
SELECT
mr.month,
mr.revenue,
COUNT(tc.user_id) AS vip_orders
FROM monthly_revenue mr
LEFT JOIN top_customers tc ON TRUE
GROUP BY mr.month, mr.revenue
ORDER BY mr.monthMySQL vs PostgreSQL Differences
| Feature | MySQL | PostgreSQL |
|---|---|---|
| String quoting | Single or double quotes | Single quotes only |
| Case sensitivity | Tables case-insensitive on Windows | Case-sensitive by default |
| Date truncation | DATE_FORMAT() | DATE_TRUNC() |
| String concat | CONCAT(a, b) | a || b or CONCAT(a, b) |
| Limit syntax | LIMIT 10 | LIMIT 10 (same) |
| Booleans | TINYINT(1) or BOOL | Native BOOLEAN |
Use DevToolkit's SQL Formatter to instantly format any SQL query — supports MySQL, PostgreSQL, SQLite, and T-SQL with configurable indentation.