skip to content

Is the comma join FROM orders o, customers c WHERE o.customer_id = c.id the same as INNER JOIN ... ON?

level: middleimportance: should knowfreq 58%

answer

  1. Start by asking what a comma in FROM means
  2. Cross product first, then the WHERE filter
  3. Same rows, different readability
  4. One form cannot express a preserved side
  5. JOIN binds tighter than the comma

basics

~20 s

For an inner join the two forms return exactly the same rows: a comma in FROM is a cross join, and the WHERE predicate then filters it. Explicit JOIN ... ON is preferred because it separates join conditions from filters and can express outer joins.

solid answer

~50 s

Semantically, yes. A comma between table references means a cross product, and the `WHERE` predicate reduces it to the matching pairs — precisely the inner-join definition. The result sets are identical, and this is a *language* equivalence, not a promise about any particular engine. The reasons to prefer explicit syntax are about writing and reading. The `ON` clause keeps each join's condition next to the table it joins, so a five-table query is readable and a missing condition is obvious rather than being buried among genuine filters in `WHERE`. Comma syntax cannot express an outer join at all — there is no place to say which side is preserved — so a query written in comma style must be rewritten the moment a `LEFT JOIN` is needed. And precedence bites: in `FROM a, b JOIN c ON …`, the `JOIN` binds `b` to `c`, not `a`, which surprises readers of a mixed-style query. Treat comma joins as legacy syntax you can read but do not write.

code

sql · 8 lines
sql
-- Equivalent for inner joins
SELECT o.id, c.name
FROM orders o, customers c
WHERE o.customer_id = c.id;

SELECT o.id, c.name
FROM orders o
INNER JOIN customers c ON o.customer_id = c.id;

go deeper

for a junior

Know that both forms are inner joins over the same rows, and that INNER JOIN ... ON is the style to write in new code.

for a middle

Explain the equivalence from first principles — comma is a cross join, WHERE filters it — and list the concrete advantages of explicit syntax, including the outer-join limitation.

for a senior

Show judgment about legacy code: convert a FROM clause wholesale rather than piecemeal, because JOIN binds tighter than the comma, and know that the equivalence stops at outer joins.

for a principal

Treat it as a codebase-consistency call — pick one syntax, enforce it in review or lint, and weigh the cost of touching long-lived queries against the readability and safety gains.

## The two spellings ```sql -- comma ("implicit") join SELECT o.id, c.name FROM orders o, customers c WHERE o.customer_id = c.id AND o.status = 'PAID'; -- explicit join SELECT o.id, c.name FROM orders o INNER JOIN customers c ON o.customer_id = c.id WHERE o.status = 'PAID'; ``` Both return the same rows. In standard SQL, a comma between two table references in `FROM` denotes a cross join: every row of the left paired with every row of the right. `WHERE` then keeps the pairs where the predicate is TRUE. "Cross product, then filter for TRUE" is exactly the definition of an inner join, so the two forms are the same query said two ways. The explicit form is sometimes called ANSI or SQL-92 join syntax; the comma form predates it. Note the scope of that equivalence: it holds for **inner** joins. Once outer joins enter the query, `ON` and `WHERE` stop being interchangeable, because an outer join adds NULL-extended rows *between* the two steps. ## Why explicit syntax won **Join conditions stop hiding among filters.** In the comma form, `o.customer_id = c.id` (structural: how the tables relate) and `o.status = 'PAID'` (a business filter) sit in the same list, separated by `AND`. With five tables you have four structural predicates mixed into whatever filters the report needs, and a reader has to reconstruct the join graph in their head. Explicit syntax puts each condition beside the table it belongs to. **A missing condition is visible.** Forgetting a comma-join predicate is silent: the query still parses, still runs, and returns the cross product — usually far too many rows, sometimes just slowly wrong. Forgetting an `ON` clause is a syntax error in the explicit form, because `JOIN` requires `ON` or `USING`. The stricter syntax turns a runtime data bug into a compile-time complaint. **Outer joins are inexpressible.** There is no comma spelling for "keep the unmatched left rows". You cannot mark a side as preserved in a `WHERE` predicate, because by then the pairing step is over. A codebase written in comma style has to be converted the first time a query needs to preserve unmatched rows — and mixing the two styles in one `FROM` clause is where readers get lost. Some engines historically offered proprietary operators inside `WHERE` for this; they are non-standard, not portable, and long discouraged. **Precedence is not what people assume.** A `JOIN` expression binds more tightly than a comma. So in ```sql FROM a, b JOIN c ON b.id = c.b_id ``` the `JOIN` pairs `b` with `c`, and the result is cross-joined with `a`. Readers who scan left to right often expect `a` to be involved. This is a real trap in half-migrated code, and a reason to convert a `FROM` clause wholesale rather than one join at a time. **Correlation names still behave the same.** Both forms alias tables the same way, and in both the alias replaces the table name for the rest of the query. That part is not a difference. ## What about more than two tables? Comma syntax scales grammatically — `FROM a, b, c, d WHERE …` is legal — but the readability cost grows with each table, and so does the chance that one structural predicate is missing. Explicit syntax makes the join order visible as a chain, one `JOIN … ON` per line, and each condition provably present. ## Is one faster? This question is about the language, not the engine, and the honest answer is that the two forms express the same logical result — a mature optimizer is free to execute either the same way. Choose the explicit form for clarity and for outer-join capability, not on a performance claim. ## The interview answer "They are equivalent for inner joins — a comma is a cross join and `WHERE` filters it. I still write explicit `JOIN … ON` because it separates structure from filters, makes a forgotten join condition a syntax error instead of a Cartesian product, and is the only syntax that can express outer joins. And I never mix the two, because `JOIN` binds tighter than the comma."

  • What happens if you forget the join predicate in each form?
    In comma syntax the query still runs and returns the full cross product — a silent data bug, often noticed only as an absurd row count. In explicit syntax, `JOIN` without `ON` or `USING` is a syntax error, so the mistake is caught before the query ever executes.
  • In `FROM a, b JOIN c ON b.id = c.b_id`, which tables does the ON clause join?
    `b` and `c`. A `JOIN` expression binds more tightly than the comma, so `b JOIN c` is evaluated as one table reference and then cross-joined with `a`. Mixing the two styles in one FROM clause is exactly how this trap is sprung; convert a query wholesale.
  • Does the equivalence still hold once outer joins are involved?
    No. It holds only for inner joins, where pairing and filtering are the whole story. An outer join inserts NULL-extended rows between those steps, so a predicate in ON and the same predicate in WHERE no longer mean the same thing — and comma syntax has no way to request the preservation at all.

saying these in an interview costs you the question

  • Says the comma form returns a Cartesian product even with a WHERE predicate
  • Claims explicit JOIN syntax is faster
  • Thinks comma syntax can express a LEFT JOIN
  • Assumes JOIN in a mixed FROM clause binds to the first table
  • Believes the two forms return different row counts

context