SQL Query Explainer: Plain-English Breakdown & Tips
Paste a SQL query and get a clause-by-clause plain-English explanation, plus rule-based suggestions for common mistakes like missing WHERE clauses or SELECT *.
Plain-English SQL explanations from pattern matching, not a database engine
This is worth stating clearly: this tool does not connect to a database and does not produce a real execution plan the way EXPLAIN does in Postgres or MySQL. It reads the text of your query, finds clause keywords with a keyword-detecting regex, and builds a sentence for each clause describing what that clause does structurally. It also runs a short list of rule-based checks for common query smells. Everything happens in the browser; no query text is transmitted anywhere.
Why string literals get masked before scanning
A naive keyword search would break the moment someone's WHERE clause filters on a string containing the word from or select. Before any clause detection runs, the tool builds a masked copy of the query where every character inside a quoted string is replaced with the letter x, keeping spaces intact so lengths and word boundaries still line up. Clause keywords are searched for in this masked copy, but the original text is used when displaying the clause body back to you.
The rule-based warnings
Alongside the clause breakdown, the tool applies a fixed set of checks and appends a warning whenever one triggers. These are heuristics, not guarantees; a query can trip a warning and still be perfectly correct for its context.
| Condition detected | Warning raised |
|---|---|
SELECT * | Suggests naming specific columns to reduce data transfer and avoid breakage if columns are added later. |
| JOIN with no ON or USING | Flags a likely cross join, every row paired with every row, which is rarely intentional. |
| No LIMIT, TOP or FETCH | Warns that an exploratory SELECT could return far more rows than expected. Skipped for grouped queries and single row aggregates. |
| Limit without ORDER BY | Notes that the rows you get back are not guaranteed to be the same each run. |
= NULL in a condition | Explains that this is never true and that IS NULL is needed. |
| LIKE starting with % | Warns that a normal index cannot be used, so every row is scanned. |
| Function on a column | Warns that something like YEAR(created_at) = 2024 usually prevents index use. |
| NOT IN with a subquery | Warns that one NULL in the subquery makes the whole condition return nothing, and suggests NOT EXISTS. |
| AND with OR, no parentheses | Reminds you that AND binds tighter than OR. |
| Comma join, no WHERE | Flags an accidental cross join. |
| ORDER BY RAND() | Warns that the whole table is sorted on every run. |
| Large OFFSET | Suggests keyset paging, because skipped rows are still read. |
| UPDATE with no WHERE | Flags that every row in the table would be modified. |
| DELETE with no WHERE | Flags that every row in the table would be removed. |
| INSERT with no column list | Warns that values are assumed to be in the table's exact column order, which breaks silently if the schema changes. |
| Wrong value count | Flags a row that does not match the listed columns, which the database would reject. |
| DROP or TRUNCATE | Reminds you that the data is gone for good without a backup. |
Column and JOIN parsing detail
Top-level comma splitting
Column lists are split on commas, but only at parenthesis depth zero, so a function call like COALESCE(a, b) inside a SELECT list is not incorrectly broken into two separate columns.
Alias detection
Both explicit AS aliases in SELECT lists and implicit table aliases in FROM and JOIN clauses are matched with dedicated regex patterns and rendered as "renamed to" or "aliased as" in the explanation.
Database documentation
- PostgreSQL EXPLAIN documentation is what to reach for when you need a real, engine-generated execution plan with actual cost estimates rather than a structural description.
- MySQL EXPLAIN documentation covers the equivalent for MySQL and MariaDB.
- ISO/IEC 9075 (SQL standard) defines the clause semantics this tool's explanations are grounded in.
- Use The Index, Luke is a good next stop for understanding why some of these warnings, like missing WHERE clauses or cross joins, matter for performance.
Queries worth explaining
Reviewing a teammate's pull request that includes a raw SQL migration or query, understanding a legacy query inherited from a previous engineer, double checking an UPDATE or DELETE statement's WHERE clause before running it against production, and getting a quick sanity check on a generated query from an ORM or query builder before trusting it.
FAQ: SQL Query Explainer
No, this tool never connects to a database or executes anything, it only reads and pattern-matches the text of your query to explain its structure. It's completely safe to paste queries containing real table or column names, since nothing is executed or transmitted anywhere.
The explainer reads SELECT statements (every JOIN type, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, TOP, FETCH, UNION, INTERSECT and EXCEPT), queries that start with WITH, and INSERT, UPDATE and DELETE statements. CREATE, ALTER, DROP and TRUNCATE get a short description. Highly vendor-specific syntax may not parse perfectly.
SELECT * pulls back every column in a table, including ones you don't need and ones that might be added later, which increases data transfer, can silently break application code that expects a fixed column order, and makes a query's actual intent harder to read. Explicitly naming the columns you need is considered better practice in most production codebases.
An UPDATE or DELETE without a WHERE clause applies to every single row in the table, this is one of the most common and most damaging SQL mistakes, often caused by accidentally running a statement before finishing the WHERE clause. This tool flags it clearly so you catch it before running the query against a real database.
A JOIN normally needs a matching condition (using ON or USING) to determine how rows from the two tables relate to each other. Without one, most databases perform a cross join, pairing every row in one table with every row in the other, which can silently produce a massive, incorrect result set and put heavy load on the database.
Yes. Each subquery is explained on its own, with a label that says where it sits, for example inside WHERE or an IN list. Queries that start with WITH get a short line per CTE, then the main query, then a breakdown of what each CTE does. Very deep nesting is cut off after four levels to keep the result readable.
No, this tool explains what a query does in plain language and flags a handful of common structural mistakes, it does not analyze performance, indexes, or execution plans. For performance analysis, use your database's own EXPLAIN or EXPLAIN ANALYZE command, which reflects your actual data and schema.
From the blog
Deep dives on the things these tools touch
Minification, UUID collisions, diffing API responses, and the other questions that come up around this toolset.