Utility Hub
Developer

How to Format SQL

Why SQL formatting matters, how to structure SELECT, JOIN, WHERE, GROUP BY, and ORDER BY clauses, and practical tips for writing readable queries.

SQLDatabasesDeveloper Tools

Why SQL formatting matters

A SQL query that works and a SQL query that is easy to work with are not the same thing. Unformatted SQL is difficult to read, hard to debug, and error-prone to modify:

select u.id,u.name,o.total from users u join orders o on u.id=o.user_id where o.total>100 order by o.total desc

That query fits on one line, but finding the join condition or adding a WHERE clause requires careful reading. Formatted:

SELECT
  u.id,
  u.name,
  o.total
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.total > 100
ORDER BY o.total DESC

The logic is immediately visible. Adding a new column or a second join condition takes seconds.

Formatting SQL does not execute the query or validate it against a database schema. A formatted query can still have logical errors or reference columns that do not exist.


SELECT

Put the SELECT keyword on its own line. List each column on a separate line, indented. This makes it easy to add, remove, or comment out individual columns without disrupting the rest.

SELECT
  user_id,
  first_name,
  last_name,
  created_at
FROM users

For a SELECT *, it is acceptable to keep it on one line — but in production code, prefer naming columns explicitly so your code is resilient to schema changes.

Aliases should follow the column immediately:

SELECT
  u.id          AS user_id,
  u.created_at  AS registered_on,
  COUNT(o.id)   AS order_count

JOIN

Place each JOIN on its own line at the same indentation level as FROM. The ON condition follows on the same line, or on the next line if the condition is long.

FROM orders o
JOIN users u ON o.user_id = u.id
JOIN products p ON o.product_id = p.id
LEFT JOIN discounts d ON o.discount_id = d.id

Use explicit JOIN types: INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL OUTER JOIN. Avoid bare JOIN with no modifier — while JOIN defaults to INNER JOIN in SQL, being explicit removes ambiguity.


WHERE

Start WHERE on a new line. Place each condition on its own line with the logical operator (AND / OR) at the start of the line:

WHERE
  o.status = 'completed'
  AND o.total > 100
  AND u.country = 'GB'

Leading AND / OR makes it easy to comment out a condition during debugging without needing to worry about whether it was at the start or end of the clause.

Grouped conditions with parentheses:

WHERE
  (u.role = 'admin' OR u.role = 'moderator')
  AND u.active = true

GROUP BY and HAVING

SELECT
  country,
  COUNT(*) AS user_count
FROM users
WHERE active = true
GROUP BY country
HAVING COUNT(*) > 50
ORDER BY user_count DESC

List each group-by column on a separate line if there are multiple:

GROUP BY
  country,
  plan_type

ORDER BY

ORDER BY
  last_name ASC,
  first_name ASC,
  created_at DESC

Always specify ASC or DESC explicitly — default ordering is ascending, but making it visible prevents confusion.


Nested queries and subqueries

Indent the subquery one level deeper than the surrounding query. Wrap it in parentheses and alias it:

SELECT
  u.name,
  recent.last_order_date
FROM users u
JOIN (
  SELECT
    user_id,
    MAX(created_at) AS last_order_date
  FROM orders
  WHERE status = 'completed'
  GROUP BY user_id
) AS recent ON u.id = recent.user_id

For complex subqueries, consider a Common Table Expression (CTE) with WITH, which moves the subquery to the top and gives it a meaningful name:

WITH completed_orders AS (
  SELECT
    user_id,
    MAX(created_at) AS last_order_date
  FROM orders
  WHERE status = 'completed'
  GROUP BY user_id
)
SELECT
  u.name,
  co.last_order_date
FROM users u
JOIN completed_orders co ON u.id = co.user_id

CTEs often make complex queries far more readable than deeply nested subqueries.


General readability tips

Capitalise keywords. SELECT, FROM, WHERE, JOIN, ON, AND, GROUP BY — all in uppercase. Column names and table names in the case used by your schema. This separation makes the SQL structure visible at a glance.

Align aliases. If your editor supports it, align the AS keyword in a column list for visual clarity (optional — some style guides prefer not to).

Use meaningful aliases. u for users and o for orders is fine. a for orders is confusing.

Consistent spacing around operators. Write o.total > 100 not o.total>100.

One clause per line. SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT — each on its own line at the base indentation level.

Use the SQL Formatter to automatically apply consistent formatting to any query, then adjust the output to match your team's conventions.