PostgreSQL Inner Join
INNER JOIN returns only the rows that have matching values in both joined tables, discarding anything that does not match on either side.
How INNER JOIN Works
For each row in the left table, PostgreSQL searches the right table for rows where the join condition is true. Every matching pair is combined into one output row. If a left-table row has no match at all, it is left out of the result entirely, and the same applies symmetrically to right-table rows.
Simple Inner Join
SELECT e.name, d.department_name
FROM employees AS e
INNER JOIN departments AS d ON e.department_id = d.id;Joining Three Tables
INNER JOIN chains naturally: each additional JOIN clause narrows the result further to rows that match across every joined table. Order rarely matters for correctness, though it can affect readability and, in large datasets, performance.
Three-Way Inner Join
SELECT o.id AS order_id, c.name AS customer, p.name AS product
FROM orders AS o
INNER JOIN customers AS c ON o.customer_id = c.id
INNER JOIN order_items AS oi ON oi.order_id = o.id
INNER JOIN products AS p ON p.id = oi.product_id;Combining with WHERE and Aggregates
Because INNER JOIN already filters to matched rows, it pairs well with WHERE clauses for further filtering and with GROUP BY for per-entity summaries, such as counting orders per customer.
Inner Join with Aggregation
SELECT c.name, COUNT(o.id) AS order_count
FROM customers AS c
INNER JOIN orders AS o ON o.customer_id = c.id
GROUP BY c.name
ORDER BY order_count DESC;- INNER JOIN is the default join when you write plain JOIN.
- Rows without a match on either side are excluded from the output.
- It is the right choice when you only care about entities that have a related record.
- Chaining multiple INNER JOINs progressively narrows the result set.