Customers Without Orders in SQL

An anti-join finds the rows in one table that have no match in another, such as customers who never placed an order.

Example query

This example assumes: customers(id bigint, email text, created_at timestamptz), orders(id bigint, customer_id bigint, order_date date). It is written in PostgreSQL syntax, and your table and column names will differ from these.

SELECT c.id, c.email, c.created_at
FROM customers c
WHERE NOT EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.id
)
ORDER BY c.created_at;

LEFT JOIN version

SELECT c.id, c.email, c.created_at
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL
ORDER BY c.created_at;

How it works

  • NOT EXISTS keeps a customer only when the subquery finds no matching order.
  • The LEFT JOIN version keeps every customer and then filters to those where the joined order columns are null, which means no match was found.
  • Both return the same rows; NOT EXISTS is usually clearer and cannot be affected by duplicate orders.

MySQL, BigQuery, SQL Server and SQLite differences

  • Both forms work in every major database. Avoid NOT IN (SELECT customer_id FROM orders): a single null in the subquery makes it return no rows.

Common mistakes

  • NOT IN with a nullable column returns nothing if any value is null; use NOT EXISTS.
  • In the LEFT JOIN version, test a column that is never null in a real match (the order id), not a nullable one.
  • 'No orders' depends on the window: add a date condition inside the subquery to find customers with no recent orders.

Ask for it in plain English

Instead of writing the query yourself, you can type the question. SchemaChat turns it into SQL against your connected database or uploaded file, runs it, and shows the SQL and the figures it used so you can check the answer before you share it. Check that the query matches the definition your business uses.

  • Which customers have never placed an order?
  • Which customers haven't ordered in the last 6 months?

Frequently asked questions

What is customers without orders in SQL?
An anti-join finds the rows in one table that have no match in another, such as customers who never placed an order.
How does the customers without orders query work?
NOT EXISTS keeps a customer only when the subquery finds no matching order. The LEFT JOIN version keeps every customer and then filters to those where the joined order columns are null, which means no match was found. Both return the same rows; NOT EXISTS is usually clearer and cannot be affected by duplicate orders.
What commonly goes wrong with customers without orders in SQL?
NOT IN with a nullable column returns nothing if any value is null; use NOT EXISTS.