SQL

SQL INNER JOIN: Syntax, Usage, and Examples

The SQL INNER JOIN keyword is one of the most fundamental and frequently used tools in relational databases. It combines rows from two or more tables based on a related column between them. Unlike outer joins, which may include unmatched rows, INNER JOIN SQL returns only rows where the join condition finds a match in both tables.

Mastering SQL INNER JOIN is essential for writing efficient, accurate queries in structured databases such as MySQL, PostgreSQL, SQL Server, and Oracle.


How SQL INNER JOIN Works

The INNER JOIN clause compares values in the specified columns of two tables and returns the rows where a match is found. The syntax is as follows:

SELECT table1.column, table2.column
FROM table1
INNER JOIN table2
ON table1.common_column = table2.common_column;

If a row in either table lacks a match in the other, it will be excluded from the results.


Basic Example of INNER JOIN SQL

Suppose you have two tables:

  • customers (with columns: id, name)
  • orders (with columns: order_id, customer_id, amount)

You can combine these to display each customer's orders:

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

This query retrieves only those customers who have placed at least one order.


When to Use SQL INNER JOIN

Use INNER JOIN SQL when:

  • You need only the rows where there’s a valid relationship between two tables.
  • You’re building reports or analytics dashboards based on relational data.
  • You want to prevent NULL values in your output from unmatched rows.
  • Your data model enforces referential integrity and expects matches.

INNER JOIN SQL is used heavily in OLTP (Online Transaction Processing) systems where data normalization is common.


INNER JOIN SQL in Multi-Table Joins

You can use multiple INNER JOIN clauses to bring together more than two tables. Here’s an example that combines employees, departments, and locations:

SELECT e.name, d.department_name, l.city
FROM employees e
INNER JOIN departments d ON e.department_id = d.id
INNER JOIN locations l ON d.location_id = l.id;

This results in a comprehensive dataset linking employees to departments and their respective cities.


Filtering Results in INNER JOIN

You can refine your joined data by adding WHERE clauses:

SELECT p.name, o.quantity
FROM products p
INNER JOIN orders o ON p.id = o.product_id
WHERE o.quantity > 10;

This query displays products with order quantities over 10, only for matched records.


INNER JOIN vs LEFT JOIN SQL

Understanding the difference between these is critical:

  • SQL INNER JOIN: Only includes records with matching keys in both tables.
  • LEFT JOIN: Includes all records from the left table and matched records from the right. If there’s no match, NULL appears.

Example:

-- INNER JOIN
SELECT c.name, o.date
FROM customers c
INNER JOIN orders o ON c.id = o.customer_id;

-- LEFT JOIN
SELECT c.name, o.date
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id;

The LEFT JOIN shows all customers, even those with no orders (their order info will be NULL), while the INNER JOIN filters them out.


INNER JOIN vs OUTER JOIN SQL

Let’s compare:

  • INNER JOIN SQL: Returns only matching rows.
  • LEFT OUTER JOIN: Includes unmatched left-table rows.
  • RIGHT OUTER JOIN: Includes unmatched right-table rows.
  • FULL OUTER JOIN: Includes unmatched rows from both tables.

Illustration:

If TableA has 5 rows and TableB has 5 rows, but only 3 pairs match:

  • INNER JOIN: 3 rows returned
  • LEFT JOIN: 5 rows from TableA, with NULL for unmatched
  • FULL OUTER JOIN: 7 rows (3 matched + 2 unmatched from each table)

Advanced INNER JOIN SQL Examples

INNER JOIN with GROUP BY

SELECT c.name, COUNT(o.order_id) AS total_orders
FROM customers c
INNER JOIN orders o ON c.id = o.customer_id
GROUP BY c.name;

This groups orders by customer name, counting only matched records.

INNER JOIN with Aggregation and HAVING

SELECT d.department_name, COUNT(e.id) AS total_employees
FROM departments d
INNER JOIN employees e ON d.id = e.department_id
GROUP BY d.department_name
HAVING COUNT(e.id) > 5;

This filters results to only departments with more than five employees.


INNER JOIN SQL with Self-Join

A self-join allows you to join a table to itself. Useful for hierarchical data like employees and managers:

SELECT e.name AS employee, m.name AS manager
FROM employees e
INNER JOIN employees m ON e.manager_id = m.id;

This matches employees to their managers in the same table.


INNER JOIN Using Subqueries

SELECT e.name, s.total_sales
FROM employees e
INNER JOIN (
  SELECT employee_id, SUM(amount) AS total_sales
  FROM sales
  GROUP BY employee_id
) s ON e.id = s.employee_id;

This joins the employees table to an aggregated subquery of total sales.


What Is INNER JOIN in SQL: Key Takeaways

  • Returns only rows with matching values in both tables.
  • Does not return unmatched rows (unlike outer joins).
  • Syntax requires a valid ON condition with matching keys.
  • Often used with indexes to optimize performance.
  • Ideal for filtering and combining normalized relational data.

Common Mistakes with INNER JOIN SQL

  1. Incorrect ON condition: Always ensure you're joining on columns that share a logical relationship.
  2. Mismatched data types: The joined columns must be of compatible types.
  3. Unintentional duplicates: Join conditions involving many-to-many relationships can cause unexpected multiplication of rows.
  4. Forgetting to use table aliases: Especially in multi-table joins, aliases improve clarity and reduce errors.

INNER JOIN vs LEFT INNER JOIN SQL?

There’s no such thing as LEFT INNER JOIN. It’s a misnomer. You either use:

  • INNER JOIN: Matching rows only
  • LEFT JOIN: All rows from the left table, with NULLs for unmatched right rows

Use the correct terminology to avoid confusion.


Performance Considerations

  • Index your foreign key columns to speed up joins.
  • Avoid unnecessary columns in SELECT to reduce result size.
  • Use EXPLAIN or QUERY PLAN to understand execution strategies.
  • Consider INNER JOIN SQL over OUTER JOIN when you don’t need unmatched rows—it's faster and more efficient.

Example of INNER JOIN SQL in a Real-World Application

Let’s say you're building an e-commerce analytics dashboard. You might use:

SELECT p.name, SUM(oi.quantity) AS total_sold
FROM products p
INNER JOIN order_items oi ON p.id = oi.product_id
GROUP BY p.name
ORDER BY total_sold DESC;

This provides a ranked list of best-selling products.


Summary

The SQL INNER JOIN keyword allows you to:

  • Match and merge data from multiple tables
  • Ensure only relevant, matching records are included
  • Build clean, efficient queries for real-time or analytical use cases
  • Maintain performance in normalized databases

Understanding how INNER JOIN SQL differs from LEFT JOIN, OUTER JOIN, and FULL JOIN enables you to choose the best tool for your queries. With the correct indexes, join logic, and awareness of table relationships, you can build scalable, accurate database queries with confidence.

Learn SQL for Free
Start learning now
button icon
To advance beyond this tutorial and learn SQL by doing, try the interactive experience of Mimo. Whether you're starting from scratch or brushing up your coding skills, Mimo helps you take your coding journey above and beyond.

Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.

You can code, too.

© 2025 Mimo GmbH

Reach your coding goals faster