A subquery is a SELECT statement nested inside another SQL command to supply rows or values to the outer query.
A subquery is an inner SELECT statement that returns a result set used by an outer query. PostgreSQL treats the subquery as a temporary table or single value, depending on context.
Choose a subquery when you need an aggregate per row, want to filter with EXISTS/IN, or isolate logic for readability. Prefer JOINs when you need sets merged into one result for performance.
Place the subquery where a single value is expected. PostgreSQL enforces that only one row is returned, otherwise it errors.
SELECT name,
(SELECT COUNT(*)
FROM Orders o
WHERE o.customer_id = c.id) AS order_count
FROM Customers c;
Use EXISTS to keep rows that have at least one matching row in the subquery. PostgreSQL stops scanning once it finds a match, making it efficient.
SELECT *
FROM Customers c
WHERE EXISTS (
SELECT 1
FROM Orders o
WHERE o.customer_id = c.id
AND o.total_amount > 100);
Yes. Wrapping a SELECT in parentheses and giving it an alias turns it into a derived table you can join or filter.
SELECT t.customer_id, t.total_spent
FROM (
SELECT o.customer_id, SUM(o.total_amount) AS total_spent
FROM Orders o
GROUP BY o.customer_id
) AS t
WHERE t.total_spent > 500;
1) Alias every derived table. 2) Index columns used in correlated predicates. 3) Avoid unnecessary correlated subqueries—rewrite as JOINs when possible for speed.
Run EXPLAIN ANALYZE on the full query. Check for sequential scans inside the subquery and add indexes or rewrite to JOIN/CTE.
Performance is usually identical because PostgreSQL inlines non-recursive CTEs. Focus on readability unless the CTE is marked MATERIALIZED.
Yes. Place the subquery in the FROM clause or use a correlated WHERE. Example: UPDATE Products p SET stock = stock - t.qty FROM (SELECT ... ) t WHERE p.id = t.product_id;