Inner Join in MySQL

Introduction
Related data across multiple tables requires joining on common columns.
INNER JOIN returns only matching rows from both tables.
It is widely used for:

  • Combining master-detail relationships
  • Normalized database queries
  • Report generation

What is an Inner Join
INNER JOIN returns rows when there is a match in both tables.
Non-matching rows from either table are excluded.

Basic Syntax

sql

SELECT columns 

FROM table1 

INNER JOIN table2 ON table1.column = table2.column

Example

sql

SELECT s.name, c.course_name 

FROM Students s 

INNER JOIN Courses c ON s.course_id = c.id; 

Only students enrolled in courses (matching course_id).

INNER JOIN with WHERE
Additional filtering after join.

sql

SELECT s.name, c.course_name 

FROM Students s 

INNER JOIN Courses c ON s.course_id = c.id 

WHERE c.duration > 6; 

Multiple INNER JOINs
Join more than 2 tables.

sql

SELECT s.name, c.course_name, d.department_name 

FROM Students s 

INNER JOIN Courses c ON s.course_id = c.id 

INNER JOIN Departments d ON c.dept_id = d.id; 

INNER JOIN with ORDER BY
Join them and sort the results.

sql

SELECT s.name, s.marks, c.course_name 

FROM Students s 

INNER JOIN Courses c ON s.course_id = c.id 

ORDER BY s.marks DESC

INNER JOIN with GROUP BY
Aggregate joined data.

sql

SELECT c.course_name, COUNT(s.id) as enrollment 

FROM Students s 

INNER JOIN Courses c ON s.course_id = c.id 

GROUP BY c.course_name; 

INNER JOIN Multiple Conditions
Complex join conditions.

sql

SELECT s.name, c.course_name 

FROM Students s 

INNER JOIN Courses c ON s.course_id = c.id 

                 AND c.status = 'Active'; 

INNER JOIN with USING
Same column name shorthand.

sql

SELECT s.name, c.course_name 

FROM Students s 

INNER JOIN Courses c USING(course_id); 

Comma Syntax (Old Style)
Pre-ANSI equivalent.

sql

SELECT s.name, c.course_name 

FROM Students s, Courses c 

WHERE s.course_id = c.id; 

INNER JOIN with Subquery
Join against subquery results.

sql

SELECT s.name, sc.avg_marks 

FROM Students s 

INNER JOIN

    SELECT course_id, AVG(marks) as avg_marks 

    FROM StudentMarks GROUP BY course_id 

) sc ON s.course_id = sc.course_id; 

Execution Order with INNER JOIN
FROM → INNER JOIN → ON → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT

Performance Considerations

  • Index both join columns
  • INNER JOIN order doesn't matter (optimizer decides)
  • Use STRAIGHT_JOIN to force order
  • Avoid functions on join columns

Important Notes

  • Only matching rows returned
  • Cartesian product if no ON condition
  • USING requires the same column names
  • Multiple matches create duplicate rows
  • NULLs never match in joins

Example Scenario
Complete student-course-department report:

sql

SELECT

    s.name,

    s.marks,

    c.course_name,

    d.department_name

FROM Students s

INNER JOIN Courses c ON s.course_id = c.id

INNER JOIN Departments d ON c.dept_id = d.id

WHERE s.marks > 80

ORDER BY s.marks DESC, c.course_name

LIMIT 50;

Common Mistakes

  • Forgetting the ON condition (cartesian explosion)
  • Non-indexed join columns (slow)
  • Functions on join columns (no index)
  • Cartesian product from wrong join order
  • Expecting non-matching rows

Key Points to Remember

  • INNER JOIN returns only matching rows
  • ON clause defines the match condition
  • Index both sides of the join
  • Multiple tables chain with additional INNER JOIN
  • USING shorthand for the same column names
  • No matches = empty result