Clause Newlines
Major SQL clauses (FROM, WHERE, GROUP BY, ORDER BY, JOIN, etc.) should each start on their own line.
Affected clauses: FROM, WHERE, HAVING, GROUP BY, ORDER BY, SORT BY, LIMIT, WINDOW, QUALIFY, RETURNING, JOIN (all types), FETCH, MERGE WHEN, VALUES, SET, UNION/INTERSECT/EXCEPT. Note: INSERT INTO stays on one line.
Simple SELECT with FROM
select a, b, c from tselect a, b, c from tSELECT with WHERE
select a from t where x > 1select a from t where x > 1SELECT with GROUP BY and ORDER BY
select a, count(*) from t group by a order by aselect a, count(*) from t group by a order by aSELECT with HAVING
select a, count(*) from t group by a having count(*) > 1select a, count(*) from t group by a having count(*) > 1SELECT with LIMIT
select a from t limit 10select a from t limit 10UNION ALL between two SELECTs
Set operators should start on their own line like other clauses.
select a, b from t1 where x > 1 union all select c, d from t2 where y < 2select a, b from t1 where x > 1 union all select c, d from t2 where y < 2UNION inside subquery
select * from (select a from t1 union select b from t2) as combinedselect * from (select a from t1 union select b from t2) as combinedselect * from (select a from t1 union select b from t2) as combinedselect *
from (
select a
from t1
union
select b
from t2
) as combinedMixed UNION and INTERSECT
select a from t1 union select b from t2 intersect select c from t3select a from t1 union select b from t2 intersect select c from t3Recursive CTE with UNION ALL
UNION ALL inside a CTE body should get its own line.
with recursive nums as (select 1 as n union all select n + 1 from nums where n < 10) select n from numswith recursive
nums as (select 1 as n union all select n + 1 from nums where n < 10)
select n
from numswith recursive nums as (select 1 as n union all select n + 1 from nums where n < 10) select n from numswith recursive
nums as (
select 1 as n
union all
select n + 1
from nums
where n < 10
)
select n
from numsSELECT 1 trivial
select 1select 1SELECT NULL trivial
select nullselect nullBETWEEN expression
BETWEEN in WHERE clause — AND is part of the BETWEEN syntax, not a boolean operator.
select a from t where x between 1 and 10select a from t where x between 1 and 10EXISTS subquery
select a from t where exists (select 1 from t2 where t2.id = t.id)select a from t where exists(select 1 from t2 where t2.id = t.id)select a from t where exists (select 1 from t2 where t2.id = t.id)select a
from t
where exists(
select 1
from t2
where t2.id = t.id
)Window function OVER
Window function with OVER clause.
select row_number() over (partition by a order by b) from tselect row_number() over (partition by a order by b) from tWindow function with frame
Window function with frame specification.
select sum(a) over (order by b rows between unbounded preceding and current row) from tselect sum(a) over (order by b rows between unbounded preceding and current row)
from tSimple JOIN
select a from t1 join t2 on t1.id = t2.idselect a from t1 join t2 on t1.id = t2.idMultiple JOINs
select a from t1 join t2 on t1.id = t2.id left join t3 on t2.id = t3.idselect a from t1 join t2 on t1.id = t2.id left join t3 on t2.id = t3.idJOIN at same level as FROM
JOIN clauses render at the same indentation level as FROM.
select a from t1 join t2 on t1.id = t2.idselect a from t1 join t2 on t1.id = t2.idMultiple JOINs at same level as FROM
select a from t1 join t2 on t1.id = t2.id left join t3 on t2.id = t3.idselect a from t1 join t2 on t1.id = t2.id left join t3 on t2.id = t3.idJOIN with AND in ON
select a from t1 join t2 on t1.id = t2.id and t1.x = t2.xselect a from t1 join t2 on t1.id = t2.id and t1.x = t2.xExtra spaces normalized
Extra whitespace between tokens is collapsed to standard spacing.
select a , b from t where x > 1select a, b from t where x > 1Tabs normalized to spaces
select a, b from t where x > 1select a, b from t where x > 1Newlines in wrong places
Broken mid-clause — the formatter restructures clauses onto proper lines.
select a,
b from
t where
x > 1 and
y < 2select a, b from t where x > 1 and y < 2THEN starts its own line when the condition broke
Whether THEN got its own line used to depend only on whether THEN plus its result would overrun
the budget from wherever the condition happened to end. After a condition that broke, the last line
is short, so there was room and THEN glued to it — reading as part of the condition: a when
line ending and hendelse in ('INNKALT', 'NYTT_TID_STED') then to_date('2022-01-06', 'YYYY-MM-DD'),
with the then buried mid-line.
A single CASE would then alternate between the two shapes, arm by arm, depending on how each
condition's last line landed. An arm that is multi-line at all puts THEN on its own line, at the
WHEN keyword's level.
select case when a = 1 and b in ('xxxxxxxxxx', 'yyyyyyyyyy', 'zzzzzzzzzz') then 2 else 3 end as v from tselect
case
when a = 1 and b in ('xxxxxxxxxx', 'yyyyyyyyyy', 'zzzzzzzzzz')
then 2
else 3
end as v
from t