SQLINNER JOIN

INNER JOIN

Real data is rarely stored in a single table. Customer information lives in one table, their orders in another, the products they ordered in a third. JOINs are how you bring related rows from multiple tables back together in a single query — and INNER JOIN is the most common and fundamental of them.

What INNER JOIN does
An INNER JOIN returns only the rows that have a matching value in both tables. If a row in one table has no corresponding row in the other, it is left out of the result entirely.
Example tables

Consider two small tables:

id

name

1

Alice

2

Bob

3

Carla

customers above, and orders below:

id

customer_id

amount

101

1

250

102

1

75

103

2

40

Notice Carla (id 3) has placed no orders, and there is no order with a customer_id of 3.
Writing the join

INNER JOIN with an ON clause

SQL
SELECT customers.name, orders.id AS order_id, orders.amount
FROM customers
INNER JOIN orders
  ON customers.id = orders.customer_id;

The ON clause tells the database how to match rows across the two tables — here, wherever a customer’s id equals an order’s customer_id. The result:

   name  | order_id | amount
-------+----------+--------
 Alice |      101 |    250
 Alice |      102 |     75
 Bob   |      103 |     40
Alice appears twice, once per matching order — that’s expected; a join produces one output row per matching pair. Carla does not appear at all, because she has no matching row in orders.
JOIN alone means INNER JOIN
Writing just JOIN without a qualifier defaults to INNER JOIN — they are exactly equivalent. Many developers write plain JOIN for this most common case and reserve explicit qualifiers like LEFT JOIN for joins that need one.

These two queries are identical

SQL
SELECT * FROM customers JOIN orders ON customers.id = orders.customer_id;

SELECT * FROM customers INNER JOIN orders ON customers.id = orders.customer_id;
Table aliases keep it readable

Once you’re joining multiple tables, repeating full table names gets noisy. Aliases shorten them:

Using aliases

SQL
SELECT c.name, o.id AS order_id, o.amount
FROM customers AS c
INNER JOIN orders AS o
  ON c.id = o.customer_id;
Joining on more than one condition

The ON clause can combine multiple conditions with AND, useful when a match depends on more than one column:

Multi-column join condition

SQL
SELECT *
FROM order_items oi
INNER JOIN price_history ph
  ON oi.product_id = ph.product_id
  AND oi.order_date BETWEEN ph.valid_from AND ph.valid_to;
  • INNER JOIN keeps only rows with a match on both sides of the join

  • Rows with no match in the other table (like Carla, above) are dropped entirely

  • Plain JOIN and INNER JOIN are the same thing

  • If you need unmatched rows preserved, you'll want LEFT JOIN or FULL OUTER JOIN, covered next