1.Scalar, Correlated and Non-Correlated Subqueries
A scalar subquery returns exactly one value. A non-correlated subquery runs once, independent of the outer query. A correlated subquery references a column from the outer query, so PostgreSQL conceptually re-evaluates it for each outer row.
Key features
- Scalar means "returns exactly one column, one row" — usable anywhere a single value is expected
- Non-correlated subqueries can run once and be reused; correlated ones reference an outer column
- A correlated subquery in WHERE is conceptually re-evaluated per outer row, though the planner may optimize the physical execution
- Using a multi-row subquery where a scalar is expected raises "more than one row returned by a subquery used as an expression"
- EXISTS/NOT EXISTS are typically correlated and do not require the subquery to be scalar
Two independent axes: shape and dependency
- Non-correlated
- no reference to the outer query
- conceptually runs once, result reused
- e.g. (SELECT max(price) FROM products)
- Correlated
- references a column from the outer query
- conceptually re-evaluated per outer row
- e.g. (SELECT count(*) FROM orders o WHERE o.customer_id = c.id)
Command
-- scalar, non-correlated
SELECT * FROM products WHERE price > (SELECT avg(price) FROM products);
-- scalar, correlated
SELECT c.name, (SELECT count(*) FROM orders o WHERE o.customer_id = c.id) AS n
FROM customers c;Scalar vs multi-row is about shape; correlated vs non-correlated is about whether the subquery references the outer row — a subquery can be any combination of the two.