Skip to main content
Developer Tools August 3, 2026 · 5 min read

How to Format SQL Queries for Readability and Debugging

SQL doesn't care about whitespace — but your team does. Consistently formatted SQL is dramatically easier to understand during code review, faster to debug, and less prone to errors hidden by visual noise. This guide covers the widely adopted conventions.

Before and After: The Difference Formatting Makes

✗ Unformatted — hard to read at a glance

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>'2024-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 20

✓ Formatted — structure is immediately clear

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 > '2024-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 20

Key Formatting Rules

Uppercase SQL keywords

SELECT, FROM, WHERE, JOIN, GROUP BY, ORDER BY, HAVING, LIMIT — keywords uppercase, identifiers lowercase. Makes the structure scannable at a glance.

One clause per line

Each major clause (SELECT, FROM, WHERE, JOIN) starts on its own line. This is the single biggest readability improvement.

Indent column lists

Columns in SELECT, conditions in WHERE, and GROUP BY columns are indented 4 spaces from the keyword.

Align AS aliases

When multiple aliased columns are in a row, align the AS keyword vertically for easy scanning.

Put AND/OR at line start

WHERE condition AND other_condition is clearer than condition AND other_condition — the operator at the start signals continuation.

Comma-first style (optional)

Some teams put commas at the start of the next line: , column_name. Makes it easy to comment out a column without touching the previous line. Controversial — pick one and be consistent.

Using CTEs for Complex Queries

Common Table Expressions (CTEs) break a complex query into named, readable steps — like functions for SQL:

WITH
active_users AS (
    SELECT id, name, email
    FROM users
    WHERE status = 'active'
      AND created_at > '2024-01-01'
),
user_orders AS (
    SELECT
        user_id,
        COUNT(*)     AS order_count,
        SUM(total)   AS total_spent
    FROM orders
    WHERE completed_at IS NOT NULL
    GROUP BY user_id
)
SELECT
    u.name,
    u.email,
    COALESCE(o.order_count, 0) AS order_count,
    COALESCE(o.total_spent, 0) AS total_spent
FROM active_users u
LEFT JOIN user_orders o ON u.id = o.user_id
ORDER BY total_spent DESC

Automated SQL Formatters

SQLFluff

Open-source linter and formatter for SQL. Supports PostgreSQL, MySQL, BigQuery, Snowflake, and others. Integrates with CI/CD and pre-commit hooks.

pgFormatter

Specifically for PostgreSQL. Excellent for complex queries with PG-specific syntax. Available as CLI, Perl module, and web tool.

sql-formatter (npm)

JavaScript library with a simple API. Works in Node.js and browsers. Supports multiple SQL dialects.

IDE plugins

DataGrip, VS Code (SQL Formatter extension), and DBeaver all have built-in SQL formatting. Configure them to match your team's style guide.

Format SQL queries instantly — free

SQL Formatter