How to SUBQUERY in PostgreSQL

Galaxy Glossary

How do I write a subquery in PostgreSQL?

A subquery is a nested SELECT that supplies data to an outer query for filtering, aggregation, or data transformation.

Sign up for the latest in SQL knowledge from the Galaxy Team!

Description

What is a subquery in PostgreSQL?

A subquery is a SELECT statement enclosed in parentheses that returns a result set consumed by the outer query. You can place it in SELECT, FROM, WHERE, or HAVING clauses to compute values, filter rows, or build derived tables.

Why choose a subquery over a JOIN?

Use a subquery when the nested logic is easier to read, when you need aggregate results in a single column, or when the outer query depends on the result of the inner query. Use JOINs for set-based combination of rows to avoid unnecessary nesting.

What is the basic subquery syntax?

Enclose the inner SELECT in parentheses. It may be correlated (referencing outer columns) or uncorrelated. Place it where a value list, table, or scalar expression is expected.

Syntax Patterns

-- In WHERE
SELECT *
FROM Orders o
WHERE o.customer_id IN (SELECT id FROM Customers WHERE created_at > now() - interval '30 days');

-- In FROM (derived table)
SELECT s.customer_id, s.recent_total
FROM (
SELECT customer_id, SUM(total_amount) AS recent_total
FROM Orders
WHERE order_date > now() - interval '30 days'
GROUP BY customer_id
) AS s;

-- Scalar subquery in SELECT
SELECT id,
(SELECT COUNT(*) FROM OrderItems oi WHERE oi.order_id = o.id) AS item_cnt
FROM Orders o;

How do I filter rows with a subquery?

Use IN, EXISTS, =, <>, >=, or < operators. EXISTS is fastest when the inner query only needs to check existence.

SELECT *
FROM Products p
WHERE EXISTS (
SELECT 1 FROM OrderItems oi WHERE oi.product_id = p.id AND oi.quantity > 5
);

How can I use scalar subqueries in SELECT?

Return a single value to enrich each row. Ensure the subquery returns at most one row or use aggregation to avoid errors.

Can I UPDATE or DELETE using subqueries?

Yes. Use a subquery to compute the filter set or new values.

UPDATE Products p
SET stock = stock - s.qty
FROM (
SELECT product_id, SUM(quantity) AS qty
FROM OrderItems
GROUP BY product_id
) AS s
WHERE p.id = s.product_id;

Best practices for writing subqueries

1) Prefer EXISTS over IN for correlated checks. 2) Index columns referenced in subqueries. 3) Alias derived tables clearly. 4) Validate that scalar subqueries return one row.

Common mistakes to avoid

Misusing subqueries where JOINs are simpler, or forgetting to correlate inner queries leading to cartesian results.

Why How to SUBQUERY in PostgreSQL is important

How to SUBQUERY in PostgreSQL Example Usage


-- List customers who bought more than 5 distinct products in the last 30 days
SELECT c.id, c.name, recent_prod
FROM Customers c
JOIN (
  SELECT o.customer_id, COUNT(DISTINCT oi.product_id) AS recent_prod
  FROM Orders o
  JOIN OrderItems oi ON oi.order_id = o.id
  WHERE o.order_date > CURRENT_DATE - INTERVAL '30 days'
  GROUP BY o.customer_id
) AS t ON t.customer_id = c.id
WHERE recent_prod > 5;

How to SUBQUERY in PostgreSQL Syntax


-- WHERE subquery using IN
SELECT *
FROM Customers
WHERE id IN (
  SELECT customer_id
  FROM Orders
  WHERE total_amount > 100
);

-- EXISTS correlated subquery
SELECT p.id, p.name
FROM Products p
WHERE EXISTS (
  SELECT 1
  FROM OrderItems oi
  WHERE oi.product_id = p.id
    AND oi.quantity > 50
);

-- Derived table in FROM
SELECT recent.customer_id, recent.monthly_spend
FROM (
  SELECT customer_id, SUM(total_amount) AS monthly_spend
  FROM Orders
  WHERE order_date >= date_trunc('month', CURRENT_DATE)
  GROUP BY customer_id
) AS recent;

Common Mistakes

Frequently Asked Questions (FAQs)

Is a subquery slower than a JOIN?

Not necessarily. PostgreSQL can transform some subqueries into joins internally. Performance depends on indexes, data volume, and whether the subquery is correlated.

Can I nest multiple subqueries?

Yes, you can nest subqueries to any depth, but readability and performance suffer. Break complex logic into CTEs or temp tables when nesting becomes confusing.

When should I switch to a CTE?

Use a common table expression when the same subquery result is reused, when you need recursion, or when you want to improve code clarity.

Want to learn about other SQL terms?

Trusted by top engineers on high-velocity teams
Aryeo Logo
Assort Health
Curri
Rubie
BauHealth Logo
Truvideo Logo