SQL Query Visualizer

See a SQL SELECT, UPDATE or DELETE statement as a tree — the query as the root, every clause branching off it to the right — instead of formatted text.

100% client-side

SQL query (SELECT, UPDATE or DELETE)

0 characters

Formatted query


      

Query tree diagram

100%
Supports SELECT, UPDATE and DELETE as a tree: the query is the root, sources/WHERE/HAVING/GROUP BY/ORDER BY/LIMIT branch off it to the right. CREATE/INSERT and other DDL are out of scope — a schema (ER) diagram is a different kind of tool. CTEs and UNION aren't parsed either — see the FAQ below.

How the query tree diagram works

This tool runs a hand-written recursive-descent parser over your SQL — it doesn't reformat text like a pretty-printer, it builds a real abstract syntax tree (AST) and lays that tree out ROOTED AT THE QUERY ITSELF, growing left to right. The statement's head node — SELECT's column list, UPDATE's SET, DELETE's marker — is the root, drawn at the far left; every clause is a direct child branching off it to the right, the same way a dendrogram or an org chart branches, just rotated 90° so it grows sideways instead of downward:

-- Before (flat SQL text)
SELECT id FROM orders
WHERE (status = 'active' OR status = 'pending')
  AND created_at > '2024-01-01'

-- After (a tree, root at the left, branching right)
SELECT (root)
  +- FROM orders
  +- WHERE
       +- AND
            +- OR ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
            |    +- status='active'      ┊
            |    +- status='pending'     ┊ (dashed: explicit parens)
            |  ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
            +- created_at > '2024-01-01'

The dashed outline around the OR branch is exactly what the parentheses in your query meant: without them, a OR b AND c would parse as a OR (b AND c) instead, because AND binds tighter than OR in every SQL dialect — the diagram makes that precedence visible instead of leaving it to be inferred from the text. UPDATE and DELETE follow the same model: their target table(s) and WHERE clause branch off the root exactly the same way, ending in a SET or DELETE root instead of a SELECT projection.

Frequently asked questions

What SQL does this tool support?

SELECT, UPDATE and DELETE statements: for SELECT, the column list (including *, table.*, aliases, arithmetic and function calls like COUNT(id)), FROM with multiple comma-joined tables, INNER/LEFT/RIGHT/FULL/CROSS JOIN chains with their ON conditions, WHERE and HAVING with full AND/OR/NOT grouping, GROUP BY, ORDER BY, LIMIT/OFFSET/TOP, and subqueries in FROM, in WHERE (IN or EXISTS) or as a column value. UPDATE (SET, optional FROM, WHERE) and DELETE (optional USING, WHERE) use the same tree model. CREATE, INSERT and other DDL are intentionally out of scope: a schema (ER) diagram is a different kind of visualization problem, not a smaller version of this tool, so that input shows a clear, specific message instead of a wrong diagram. CTEs (WITH), UNION and window functions aren't parsed yet either.

Why is SELECT (or SET / DELETE) drawn as the root, not FROM?

The diagram is a rooted tree, not a flowchart: the statement's head node — SELECT's projection, UPDATE's SET, DELETE's marker — sits at the far left as the root, and every clause (sources, WHERE/HAVING and their AND/OR sub-trees, GROUP BY, ORDER BY, LIMIT) is a direct child branching off it to the right, the same way a dendrogram or an org chart branches — just rotated so it grows rightward instead of downward. That's a deliberate choice: it reads as "this is the query, and these are its parts" rather than as a left-to-right data flow.

How does the diagram show AND vs OR logic?

WHERE, HAVING and each JOIN's ON condition are drawn as a compact box that itself branches further right into its own AND/OR condition tree: AND and OR each get their own connector node, and explicit parentheses around a group are drawn as a dashed outline around that whole sub-tree — so (a OR b) AND c visibly shows the OR grouped separately from the outer AND.

How are subqueries shown?

A subquery is parsed with the same parser, recursively, and rendered as its own nested tree — its own root, its own branches — inside a distinctly dashed, boxed-in panel, clearly subordinate to the FROM, WHERE or column it belongs to, however deep the nesting goes.

Does the dialect selector fully support MySQL, PostgreSQL and SQL Server?

No — it's honestly scoped to the one structural difference that actually changes parsing: row-limiting syntax. Generic/ANSI and PostgreSQL use LIMIT n OFFSET m, MySQL uses the same LIMIT/OFFSET, and SQL Server uses TOP n (right after SELECT) or OFFSET m ROWS FETCH NEXT n ROWS ONLY. Identifier quoting ("double", `backtick`, [bracket]) is accepted leniently in every dialect. Proprietary functions, data types and other engine-specific syntax aren't modeled.

Is my SQL sent anywhere?

No. Formatting, parsing and rendering all happen entirely in your browser with plain JavaScript; nothing is ever uploaded to a server.