Skip to main content

Join Queries

In relational databases, data is often spread across multiple tables to maintain normalization and reduce redundancy. To retrieve data that spans multiple tables, SQL provides the JOIN operation, which combines rows from two or more tables based on a related column between them.

The most common types of joins are:

  • INNER JOIN
  • LEFT JOIN (LEFT OUTER JOIN)
  • RIGHT JOIN (RIGHT OUTER JOIN)
  • FULL OUTER JOIN
  • CROSS JOIN
  • LATERAL JOIN

Example Setup

We’ll use the following two tables throughout the examples:

Table: students

student_idnamecourse_id
1Alice101
2Bob102
3CharlieNULL

Table: courses

course_idcourse_name
101Math
102Science
103History

INNER JOIN

Definition: Returns only the rows that have matching values in both tables.

Query:

SELECT s.name, c.course_name
FROM students s
INNER JOIN courses c ON s.course_id = c.course_id;

Output:

namecourse_name
AliceMath
BobScience

Explanation: Only Alice and Bob have matching course IDs in both tables. Charlie is excluded because his course_id is NULL.

LEFT JOIN (LEFT OUTER JOIN)

Definition: Returns all rows from the left table and the matched rows from the right table. If there’s no match, the right side will contain NULL.

Query:

SELECT s.name, c.course_name
FROM students s
LEFT JOIN courses c ON s.course_id = c.course_id;

Output:

namecourse_name
AliceMath
BobScience
CharlieNULL

Explanation: All students are returned. For Charlie, there’s no course match, so course_name is NULL.

RIGHT JOIN (RIGHT OUTER JOIN)

Definition: Returns all rows from the right table and the matched rows from the left table. If there’s no match, the left side will contain NULL.

Query:

SELECT s.name, c.course_name
FROM students s
RIGHT JOIN courses c ON s.course_id = c.course_id;

Output:

namecourse_name
AliceMath
BobScience
NULLHistory

Explanation: All courses are returned. The “History” course has no enrolled student, so name is NULL.

FULL OUTER JOIN

Definition: Returns all rows from both tables. If there’s no match, unmatched columns will contain NULL.

Query:

SELECT s.name, c.course_name
FROM students s
FULL OUTER JOIN courses c ON s.course_id = c.course_id;

Output:

namecourse_name
AliceMath
BobScience
CharlieNULL
NULLHistory

Explanation: Combines results of both LEFT and RIGHT joins.

Note: MySQL doesn’t support FULL OUTER JOIN natively. To emulate it, you can use UNION:

SELECT s.name, c.course_name
FROM students s
LEFT JOIN courses c ON s.course_id = c.course_id
UNION
SELECT s.name, c.course_name
FROM students s
RIGHT JOIN courses c ON s.course_id = c.course_id;

CROSS JOIN

Definition: Produces a Cartesian product of both tables — every row from the first table is combined with every row from the second table.

Query:

SELECT s.name, c.course_name
FROM students s
CROSS JOIN courses c;

Output:

namecourse_name
AliceMath
AliceScience
AliceHistory
BobMath
BobScience
BobHistory
CharlieMath
CharlieScience
CharlieHistory

Explanation: Every student-course combination is returned.

LATERAL JOIN (PostgreSQL & SQL Server)

Definition: A LATERAL JOIN allows a subquery in the FROM clause to reference columns from preceding tables in the same FROM clause. It’s useful when you want to run a subquery for each row of another table.

Example Scenario: Suppose we have a table marks that stores multiple marks per student.

Table: marks

student_idmark
185
190
278

We want to select each student and their highest mark.

Query (PostgreSQL):

SELECT s.name, m.highest_mark
FROM students s,
LATERAL (
SELECT MAX(mark) AS highest_mark
FROM marks
WHERE marks.student_id = s.student_id
) m;

Output:

namehighest_mark
Alice90
Bob78
CharlieNULL

Explanation: For each student, the lateral subquery runs individually and finds their maximum mark.

Note:

  • MySQL 8.0+ supports this using the keyword JOIN LATERAL or CROSS JOIN LATERAL.
  • SQL Server supports similar behavior with APPLY (CROSS APPLY, OUTER APPLY).

Summary of Join Differences Across Databases

Join TypeMySQLPostgreSQLSQL ServerOracle
INNER JOIN✅ Supported✅ Supported✅ Supported✅ Supported
LEFT JOIN
RIGHT JOIN
FULL OUTER JOIN❌ (use UNION)
CROSS JOIN
LATERAL JOIN✅ (8.0+)✅ (as APPLY)✅ (as CROSS APPLY)

Key Takeaways

  • INNER JOIN → Returns only matching rows.
  • LEFT JOIN → Keeps all left rows, fills missing right with NULL.
  • RIGHT JOIN → Keeps all right rows, fills missing left with NULL.
  • FULL OUTER JOIN → Keeps all rows from both sides.
  • CROSS JOIN → Cartesian product of both tables.
  • LATERAL JOIN → Enables correlated subqueries in FROM.