Menu

MySQL INNER JOIN

Learn how MySQL INNER JOIN returns matching row pairs, use ON or USING, and understand how NULL and one-to-many matches affect results.

MySQL INNER JOIN returns a row for each pair of rows that satisfies the join condition. Rows without a match on either side are omitted. In MySQL, JOIN without a join type is equivalent to INNER JOIN.

For an overview of all MySQL join types, see the MySQL JOIN guide.

Syntax

SELECT select_list
FROM table_a AS a
INNER JOIN table_b AS b
    ON join_condition
[WHERE row_filter]
[ORDER BY sort_expression];

The ON condition defines which rows match. Use WHERE for additional filters on the joined result.

Example: join employees to departments

Create two temporary tables and add rows. Run these statements in the same session:

CREATE TEMPORARY TABLE departments (
    department_id INT PRIMARY KEY,
    department_name VARCHAR(50) NOT NULL
);

CREATE TEMPORARY TABLE employees (
    employee_id INT PRIMARY KEY,
    employee_name VARCHAR(50) NOT NULL,
    department_id INT NULL
);

INSERT INTO departments (department_id, department_name)
VALUES (10, 'Sales'), (20, 'Engineering');

INSERT INTO employees (employee_id, employee_name, department_id)
VALUES
    (1, 'Maya', 10),
    (2, 'Noah', 20),
    (3, 'Lina', NULL),
    (4, 'Aru', 30);

Join the tables on their shared department_id value:

SELECT
    e.employee_id,
    e.employee_name,
    d.department_name
FROM employees AS e
INNER JOIN departments AS d
    ON e.department_id = d.department_id
ORDER BY e.employee_id;
+-------------+---------------+-----------------+
| employee_id | employee_name | department_name |
+-------------+---------------+-----------------+
|           1 | Maya          | Sales           |
|           2 | Noah          | Engineering     |
+-------------+---------------+-----------------+

Lina is omitted because her department_id is NULL; Aru is omitted because department 30 does not exist. With =, a NULL value does not match another value. Use a LEFT JOIN when you need to keep every row from the left table, including rows without a match.

Use USING for identically named join columns

When both tables have a join column with the same name, you can use USING instead of writing the equality condition:

SELECT
    e.employee_id,
    e.employee_name,
    d.department_name
FROM employees AS e
INNER JOIN departments AS d USING (department_id)
ORDER BY e.employee_id;

The query returns the same matching rows. With SELECT *, USING returns one copy of the shared join column; an ON join returns both table columns.

One-to-many joins return one row per matching pair

If a row on one side matches several rows on the other side, the joined result contains one row for each matching pair. Use GROUP BY with an aggregate function if you want to summarize those rows instead of listing every pair.

For MySQL’s complete join syntax and other join forms, see the official JOIN documentation.