Dataslope logoDataslope

Inner Joins

The most common join — keeping only the rows that have a match in both tables — with clear visuals of what stays and what disappears.

The join you met on the previous page was an inner join, the default and most common kind. Its rule is simple and worth saying precisely: an inner join keeps only the rows that have a match in both tables. Rows with no partner are dropped.

The rule, in a picture

If an order points to a customer who exists → it appears. If a customer has no orders → they do not appear. Only the overlap survives.

Seeing what survives and what drops

This data is rigged to show the rule. There is an order with no matching customer, and a customer with no orders. Watch both vanish from an inner join:

SQL
PostgreSQL 17

The result shows Ada (two orders) and Grace (one). Linus is absent (no orders to match), and order 104 is absent (its customer 7 does not exist). That is the inner join doing its job: no match, no row.

INNER is optional

JOIN and INNER JOIN mean exactly the same thing — INNER is the default, so people usually just write JOIN. Writing it out can make your intent explicit when a query also contains outer joins.

When an inner join is the right choice

Use an inner join when you only care about rows that are connected — which is most of the time:

  • "Orders with their customer details" — you do not want customer-less orders.
  • "Students and the courses they are enrolled in" — empty enrollments are irrelevant.
  • "Products that have been sold" — unsold products are not part of the question.

The giveaway is the word with or that have: you want rows that do have a counterpart.

Joining more than two tables

Real questions often span three tables. You chain joins, each with its own ON. Here orders connect to both customers and products:

SQL
PostgreSQL 17

Each JOIN ... ON ... adds one more connected table. The pattern scales: the orders table sits in the middle, linking customers to the products they bought. This is everyday relational querying.

Check your understanding

QuestionSelect one

What rows does an inner join include in its result?

Every row from both tables, matched or not.

Only rows that have a matching row in both tables.

Only rows from the left table.

Only rows where both tables are empty.

QuestionSelect one

A customer named Linus has no orders. In an INNER JOIN between customers and orders, does Linus appear?

Yes, with all his order columns shown.

No — with no matching order, an inner join drops him entirely.

Yes, but only if the orders table is empty.

It causes an error.

QuestionSelect one

You want "all products that have actually been sold." Which join expresses this best?

An outer join that keeps unsold products too.

An inner join between products and orders, keeping only products with a matching order.

No join at all; just select from products.

A join with no ON condition.

Practice challenge

SQL Challenge
PostgreSQL 17
Orders with customer details

Join orders to customers. Return one row per order with the customer's name, their city, and the order amount, sorted from the largest amount to the smallest.

On this page