SQL

Snowflake SQL Formatter

Format Snowflake SQL with QUALIFY, FLATTEN, VARIANT paths and time travel clauses laid out properly.

Private by design — your data never leaves your device.
✓ Free forever✓ No sign-up✓ No ads✓ Works offline once loaded

Snowflake SQL Formatter

Format Snowflake SQL with QUALIFY, FLATTEN, VARIANT paths and time travel clauses laid out properly.

Input

Your Snowflake SQL

Nothing is uploaded.

Output

Formatted Snowflake SQL

Your result appears herePaste on the left and select “Format Snowflake SQL”

Snowflake queries have a particular shape: raw semi-structured data in a VARIANT column, a LATERAL FLATTEN to expand an array inside it, colon paths and :: casts to pull typed values out, and a QUALIFY at the bottom to keep one row per key. Written on one line it is dense; broken into clauses it reads as the four-step pipeline it actually is.

With the Snowflake dialect selected, the formatter recognises all of that syntax as first-class, including the time travel clauses that make a table reference carry a point in history. Everything runs locally — Snowflake queries tend to be full of real table names and identifiers, and none of it leaves your browser.

How it works

How to use the snowflake formatter

  1. 1

    Paste the query

    From a Snowsight worksheet, a dbt model, a task definition or the query history.

  2. 2

    Format and check the QUALIFY and the FLATTEN

    Those two clauses control your row count. Once they are on their own lines, an unintended fan-out from a FLATTEN is much easier to spot.

  3. 3

    Copy back into the worksheet or your model

    Plain text output with no markup, ready to paste anywhere.

Snowflake syntax the formatter treats as its own clause

  • QUALIFY. Given its own top-level line alongside WHERE, GROUP BY and HAVING, which is exactly where it belongs logically: QUALIFY filters on the result of a window function after it has been computed, the way HAVING filters on aggregates. Without it, the same deduplication needs a subquery wrapping the whole select.
  • LATERAL FLATTEN. The table function that expands an array or object inside a VARIANT. It is printed in the FROM list beside the other sources, with the input => named argument kept on the same line, so the fan-out it introduces is visible.
  • VARIANT colon paths. payload:order_id::string combines a colon path into semi-structured data with a cast to a real type. Both are kept glued to the expression rather than spaced out as operators — payload:items[0].sku stays in one piece too.
  • Time travel. AT(TIMESTAMP => …), AT(OFFSET => …), BEFORE(STATEMENT => …) and CLONE … BEFORE(…) are parsed as part of the table reference. One quirk: with OFFSET the argument is broken onto extra lines, because OFFSET is also a pagination keyword. Using the TIMESTAMP form when you can gives cleaner output.
  • Semi-structured functions. PARSE_JSON, OBJECT_CONSTRUCT, ARRAY_AGG and the rest format like ordinary function calls, with nested arguments indented.

Time travel is a table-reference modifier

It is easy to read AT and BEFORE as clauses of the query. They are not — they attach to a single table reference and change which version of that table is read. That means different tables in the same query can be read at different points in time, which is occasionally exactly what you want and occasionally the bug.

Formatting puts each source on its own line in the FROM list, so a stray time travel modifier on one of three joined tables becomes visible. Retention is a property of the account and table, not the query: the default window is one day, extendable up to ninety on Enterprise editions, and a query asking for a point outside it fails rather than approximating.

Warehouse cost, and what a formatter cannot change

Snowflake bills warehouse credits by size and uptime, with per-second billing after a sixty-second minimum. What drives that bill is data scanned, spilling to remote storage, and how long a warehouse stays awake — not how your SQL is laid out. Formatting has no effect on credit consumption. The parser strips whitespace before planning.

What it does affect is the review step before the query runs. Pruning depends on the filters in your WHERE clause matching the table clustering; a query whose predicates each sit on their own line is one you can check against the clustering key in a few seconds. For the actual numbers, the query profile and QUERY_HISTORY are the sources of truth, and this tool has no access to either — it never connects to an account.

Common questions

Snowflake Formatter FAQ

Does it understand QUALIFY?

Yes. QUALIFY is recognised as a top-level clause and printed alongside WHERE and GROUP BY, with the window function expression indented beneath it.

Will my VARIANT colon paths survive formatting?

Yes. Expressions like payload:items[0].sku::string are kept as a single expression with no spaces inserted around the colon, the bracket subscript or the cast.

Why does AT(OFFSET => -300) come out on several lines?

Because OFFSET is also a pagination keyword and the tokeniser gives it clause-level treatment. The query is unchanged. If the layout bothers you, the TIMESTAMP form of time travel formats cleanly.

Can it format a Snowflake stored procedure?

It formats the SQL statements. A procedure body written in JavaScript, Python or Snowflake Scripting is a different language, and the formatter does not attempt to lay out its control flow.

Does the tool connect to my Snowflake account?

No. There is no credential field and no network call. It is a text tool that runs in your browser and never sees your data or your warehouse.