Why would you CROSS JOIN a table to a one-row subquery such as (SELECT SUM(amount) AS total FROM sales)?
answer
- only one row on the right side
- N times 1 is still N
- every row gets the same extra column
- attaches a grand total to each row
basics
~20 sPairing N rows with a one-row subquery yields N rows, attaching that subquery's value — a grand total, say — to every row, so each row can be compared against it without repeating the aggregate query in the select list.
solid answer
~50 sBecause N × 1 = N, crossing a table with a single-row subquery does not multiply anything: it simply widens every row with the subquery's columns. That makes it the idiomatic way to bring a scalar summary — a grand total, a global maximum, a run's parameters — into scope for every row, so you can write `s.amount * 100.0 / t.total` for a percentage of total. No join predicate is needed or possible, since there is exactly one candidate row on the right. The idiom is safe only while the subquery really returns one row: return zero and the whole result vanishes (N × 0 = 0); return three and every row is silently tripled. An unfiltered aggregate with no `GROUP BY` always returns exactly one row, which is why this shape is the reliable version.
code
sql · 6 linesSELECT s.region,
s.amount,
s.amount * 100.0 / t.total AS pct_of_total
FROM sales s
CROSS JOIN (SELECT SUM(amount) AS total FROM sales) AS t
ORDER BY pct_of_total DESC;go deeper
Recall that crossing a table with a one-row source keeps the row count unchanged and just adds that row's columns to every row.
Explain the N times 1 arithmetic, why no join predicate is possible or needed, and what happens when the subquery returns zero or several rows instead of one.
Show the review instinct: verify the right side is provably single-row, prefer LEFT JOIN ... ON TRUE where emptiness is possible, and reach for a window function when the summary is per group.
Set the expectation that any deliberate Cartesian product carries its justification — a documented single-row guarantee — so the idiom cannot quietly become an accidental product after a later edit.
## The arithmetic that makes it safe A `CROSS JOIN` multiplies row counts. Crossing a 500-row table with a one-row source gives 500 × 1 = 500 rows — the original rows, each widened by the extra columns. Nothing is duplicated and nothing is lost. That degenerate case of the Cartesian product is the whole point of the idiom. ```sql SELECT s.region, s.amount, s.amount * 100.0 / t.total AS pct_of_total FROM sales s CROSS JOIN (SELECT SUM(amount) AS total FROM sales) AS t; ``` Every sales row now carries `t.total`, so a per-row share of the overall total is a plain arithmetic expression. ## Why no join predicate appears There is only one row on the right, so there is nothing to choose between. Any `ON` condition would be either always true (redundant) or sometimes false (which would drop rows). This is one of the rare places where the absence of a join predicate is correct by construction rather than a bug — and it is worth saying so out loud in review, because a reviewer trained to look for missing predicates should be able to see immediately why this one is fine. ## What it buys over the alternatives - **Against repeating the aggregate in the select list.** You could write `(SELECT SUM(amount) FROM sales)` inline in every expression that needs it. Crossing once names the value, computes it in one place, and lets several expressions reference it. - **Against parameters.** The same shape injects run-time constants: `CROSS JOIN (SELECT DATE '2026-01-01' AS from_dt, DATE '2026-01-31' AS to_dt) p` gives a single place to change a report's window, referenced as `p.from_dt` throughout. - **Against a correlated subquery.** A correlated scalar subquery recomputes conceptually per row and cannot be reused across expressions; the crossed derived table is evaluated as one independent query. Where the summary must be computed *per group* rather than globally — a running total, or each row's share of its own region — a window function such as `SUM(amount) OVER (PARTITION BY region)` is the natural tool instead; the cross-joined subquery is for values that are the same for every row. ## The failure modes The idiom's safety rests entirely on the "exactly one row" assumption: - **Zero rows returned.** The product is `N × 0 = 0` and the entire result disappears. An aggregate with no `GROUP BY` cannot do this — `SELECT SUM(amount) FROM sales` over an empty table still returns one row containing NULL — but a subquery with a `WHERE` clause or a `GROUP BY` easily can. If the right side might be empty and you must keep the outer rows, use `LEFT JOIN … ON TRUE` instead, which NULL-extends rather than annihilating. - **More than one row returned.** The outer rows are silently multiplied by that count. This is the dangerous one: a subquery that grows a `GROUP BY` clause during a later edit turns a correct report into a duplicated one with no error anywhere. If the subquery has a `GROUP BY` or a filter that might not be unique, the shape is no longer a scalar attachment and needs a real join predicate. ```sql -- annihilation risk: the filter may match nothing FROM sales s CROSS JOIN (SELECT SUM(amount) AS total FROM sales WHERE region = 'EU') t -- safe under emptiness: keeps every sales row, total may be NULL FROM sales s LEFT JOIN (SELECT SUM(amount) AS total FROM sales WHERE region = 'EU') t ON TRUE ``` ## Reading it in review When you meet a bare `CROSS JOIN` in a query, the first question is whether the right side is provably one row. An ungrouped aggregate over a table is; a filtered subquery or a grouped one is not, and needs a second look. Documenting the assumption with a comment — or asserting it with a uniqueness constraint on the underlying data — is what keeps the idiom from decaying into an accidental product later.
- What happens if the cross-joined subquery unexpectedly returns three rows instead of one?Every outer row is paired with all three, so the result is silently tripled and any downstream aggregate is inflated threefold. Nothing errors. This is why the idiom is only safe when the right side is provably one row — an ungrouped aggregate over a table qualifies; a filtered or grouped subquery does not.
- How do you keep the outer rows when the subquery might return no rows at all?Replace the cross join with `LEFT JOIN (…) ON TRUE`. The outer rows are preserved and the subquery's columns come back NULL when it is empty, instead of the whole result collapsing to zero rows. Wrap the value in `COALESCE` if a numeric default is wanted.
- When is a window function the better tool than a cross-joined summary subquery?When the summary varies per row or per group — a per-region share, a running total, or a comparison against the group's maximum. `SUM(amount) OVER (PARTITION BY region)` computes those in place. The cross-joined subquery is for a single value that is identical for every row.
It is like stamping the same footer onto every page of a printout: one value, applied to each row, so every page can be read against the same reference number.
saying these in an interview costs you the question
- Thinks crossing with one row still multiplies the result
- Assumes a subquery returning zero rows leaves the outer rows intact
- Adds a meaningless ON condition to make the join look normal
- Uses the idiom with a GROUP BY subquery that may return many rows
- Calls any CROSS JOIN in production code an automatic bug