SQL Formatting Best Practices for Readable Queries

๐Ÿ“– 8 min read ยท Data Formats ยท Try SQL Formatter โ†’

Why SQL Formatting Matters

SQL queries can range from simple one-liners to complex multi-page statements with dozens of joins, subqueries, and window functions. Poorly formatted SQL is difficult to read, debug, and maintain. Well-formatted SQL communicates intent clearly, makes errors obvious, and allows team members to understand and modify queries quickly.

Unlike most programming languages, SQL has no enforced formatting standard. This makes consistent formatting even more important โ€” your team needs to agree on conventions and stick to them.

Keyword Capitalization

The most fundamental SQL formatting decision is whether to capitalize keywords. The two main conventions are:

Uppercase keywords (recommended)

SELECT id, name, email
FROM users
WHERE active = true
ORDER BY name ASC;

Lowercase keywords

select id, name, email
from users
where active = true
order by name asc;

Uppercase keywords are the traditional standard and make it easy to visually distinguish SQL keywords from table names, column names, and values. Most style guides recommend uppercase keywords.

Indentation & Line Breaks

Each major clause should start on a new line. Use consistent indentation (2 or 4 spaces) for continuation lines:

-- Good formatting
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.active = true
    AND u.created_at >= '2024-01-01'
GROUP BY u.id, u.name, u.email
HAVING COUNT(o.id) > 0
ORDER BY total_spent DESC
LIMIT 100;

JOIN Formatting

JOINs are one of the most complex parts of SQL queries. Format them clearly to show the relationship between tables:

SELECT
    o.id AS order_id,
    u.name AS customer_name,
    p.name AS product_name,
    oi.quantity,
    oi.price
FROM orders o
INNER JOIN users u
    ON o.user_id = u.id
INNER JOIN order_items oi
    ON o.id = oi.order_id
INNER JOIN products p
    ON oi.product_id = p.id
WHERE o.status = 'completed'
    AND o.created_at >= '2024-01-01';

Naming Conventions

Use snake_case for identifiers

โœ“ user_id, first_name, created_at

โœ— userId, FirstName, CreatedAt

Use meaningful table aliases

โœ“ FROM users u, FROM orders o

โœ— FROM users a, FROM orders b

Prefix boolean columns

โœ“ is_active, has_subscription, can_edit

โœ— active, subscription, edit

Use plural table names

โœ“ users, orders, products

โœ— user, order, product

Name foreign keys consistently

โœ“ user_id references users(id)

โœ— uid, user, fk_user

Subqueries & CTEs

For complex queries, use CTEs (Common Table Expressions) with the WITH clause instead of nested subqueries. CTEs are more readable and can be referenced multiple times:

-- CTE (preferred for complex queries)
WITH active_users AS (
    SELECT id, name, email
    FROM users
    WHERE active = true
        AND last_login >= NOW() - INTERVAL '30 days'
),
user_orders AS (
    SELECT user_id, COUNT(*) AS order_count
    FROM orders
    WHERE status = 'completed'
    GROUP BY user_id
)
SELECT
    au.name,
    au.email,
    COALESCE(uo.order_count, 0) AS orders
FROM active_users au
LEFT JOIN user_orders uo ON au.id = uo.user_id
ORDER BY orders DESC;

SQL Performance Tips

  • SELECT only needed columns โ€” Avoid SELECT * in production. Specify only the columns you need.
  • Use indexes on WHERE and JOIN columns โ€” Unindexed columns in WHERE clauses cause full table scans.
  • Filter early โ€” Apply WHERE conditions as early as possible to reduce the number of rows processed.
  • Use EXPLAIN/EXPLAIN ANALYZE โ€” Check the query execution plan to identify bottlenecks.
  • Avoid functions on indexed columns โ€” WHERE YEAR(created_at) = 2024 prevents index use. Use WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31' instead.

Format Your SQL Queries

Instantly beautify and format SQL queries in your browser.

SQL Formatter โ†’