Free tutorials & notes in Hindi & English · Clean code examples · Mobile friendly learning
MySQL + SQL · Lesson 69

LEFT JOIN and RIGHT JOIN

The Outer-Join Idea

An outer join combines matching pairs and also preserves a chosen input. LEFT JOIN preserves its left input; RIGHT JOIN preserves its right input. Missing partners are represented with NULL-extended columns.

Language test: If the requirement says “all students, even those without a class,” place students on the preserved side.

LEFT JOIN with Verified Output

SELECT s.student_id, s.student_name, c.class_name
FROM join_students AS s
LEFT JOIN classes AS c
  ON c.class_id = s.class_id
ORDER BY s.student_id;
1 | Aarav | X-A 2 | Meera | X-A 3 | Kabir | X-B 4 | Sana | X-B 5 | Vihaan | NULL

Five left rows guarantee at least five output rows. A left row can still produce more than one output row if several right rows match it. The NULL shown for Vihaan is generated by the outer join because no class row matches.

SELECT s.student_name, c.class_name
FROM join_students AS s
RIGHT JOIN classes AS c
  ON c.class_id = s.class_id
ORDER BY c.class_id, s.student_id;
Aarav | X-A Meera | X-A Kabir | X-B Sana | X-B NULL | XI-A

This keeps all classes, including XI-A. The same result is usually easier to read as:

SELECT s.student_name, c.class_name
FROM classes AS c
LEFT JOIN join_students AS s
  ON s.class_id = c.class_id
ORDER BY c.class_id, s.student_id;

RIGHT JOIN is valid MySQL syntax; the rewrite is a style choice, not a different capability.

Anti-Join: Find Unmatched Rows

SELECT s.student_id, s.student_name
FROM join_students AS s
LEFT JOIN classes AS c
  ON c.class_id = s.class_id
WHERE c.class_id IS NULL;
5 | Vihaan

Reverse the preserved side to find classes without students:

SELECT c.class_id, c.class_name
FROM classes AS c
LEFT JOIN join_students AS s
  ON s.class_id = c.class_id
WHERE s.student_id IS NULL;
30 | XI-A

ON Versus WHERE Changes the Question

Preserve all students; allow only X-A to match

SELECT s.student_name, c.class_name
FROM join_students AS s
LEFT JOIN classes AS c
  ON c.class_id = s.class_id
 AND c.class_name = 'X-A'
ORDER BY s.student_id;
Aarav | X-A Meera | X-A Kabir | NULL Sana | NULL Vihaan | NULL

Keep only final rows belonging to X-A

SELECT s.student_name, c.class_name
FROM join_students AS s
LEFT JOIN classes AS c
  ON c.class_id = s.class_id
WHERE c.class_name = 'X-A';
Aarav | X-A Meera | X-A

Neither query is universally better; they answer different requirements. State the requirement before placing the predicate.

Counts Including Zero

SELECT c.class_name,
       COUNT(s.student_id) AS student_count
FROM classes AS c
LEFT JOIN join_students AS s
  ON s.class_id = c.class_id
GROUP BY c.class_id, c.class_name
ORDER BY c.class_id;
X-A | 2 X-B | 2 XI-A | 0

COUNT(expression) ignores NULL. Counting the child primary key therefore distinguishes zero children from one match. Group by the stable class identifier as well as the displayed name.

Mistakes, Performance and Practice

  • Do not put a NULL-rejecting right filter in WHERE when the left population must remain.
  • Do not test a nullable right attribute to detect absence; test its non-nullable key.
  • Do not assume outer joins prevent row multiplication.
  • Index join keys and inspect EXPLAIN only after verifying meaning and row counts.

Practice: preserve all teachers/classes and show zero students; write both RIGHT and LEFT forms; then explain why COUNT(*) is wrong for XI-A in this dataset.

Official References

Syntax and optimizer notes were checked against the official MySQL 8.4 manual. Always test plans and row counts on your own schema and data.

Frequently Asked Questions

What does LEFT JOIN preserve?
It preserves every row from its left input. Matching right rows are added; when no match exists, right-side columns are returned as NULL.
Is RIGHT JOIN different from LEFT JOIN?
It preserves the opposite written side. Most RIGHT JOIN queries can be rewritten as LEFT JOIN by swapping table order, which many teams prefer for consistent reading.
Why did WHERE remove my unmatched rows?
A right-table condition in WHERE is tested after NULL extension. If it rejects NULL, the preserved unmatched rows disappear.
How do I find rows without a partner?
LEFT JOIN from the population to keep, then filter WHERE the partner's non-nullable primary key IS NULL.
How do I count matches while keeping zero?
Preserve parents with LEFT JOIN and COUNT a non-nullable child key. COUNT(*) counts the placeholder row and may report one instead of zero.
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

💻 Live Code Editor

This page's programs are ready here — run them, edit them, and learn. No installation needed.
Powered by OneCompiler. The code loads into the editor automatically — press Run to see the output. If the editor does not open, open it in a new tab.