SQLQuokka
Start practicing
QuestionsLearnSandboxFeaturesRoadmapFAQ
SQL Concept

SQL INNER JOIN vs LEFT JOIN Explained

Joins combine rows from two tables that match on a condition. An INNER JOIN keeps only rows with a match on both sides; a LEFT JOIN keeps every row from the left table and fills in NULL when there is no match. Most join bugs come down to choosing the wrong one.

Examples run in MySQL 8 and PostgreSQL · Updated

In short

  • INNER JOIN: only rows that match on both sides.
  • LEFT JOIN: all left rows, NULLs where the right side has no match.
  • Count matches with COUNT(right.id), not COUNT(*).
  • A WHERE on the right table can undo a LEFT JOIN.

Which rows survive

Our data has one employee without a department (Zoya) and one department without employees (Finance). An inner join drops both. A left join from employees keeps Zoya with a NULL department name; a left join from departments keeps Finance with no employees.

Which table is "left" matters: it is the one written first, after FROM. Put the table whose rows you must keep on the left.

Counting with a LEFT JOIN

When a left row has no match, the joined row still exists, with NULLs on the right. COUNT(*) counts that row as 1; COUNT(e.emp_id) skips NULLs and correctly gives 0.

The example tables

Every example on this page uses these tables. They are small on purpose, so you can check each result by eye.

employees

emp_idnamedept_idsalarymanager_idhire_date
1Aarav1095000NULL2021-03-01
2Diya108800012022-06-15
3Kabir107200012023-01-10
4Meera2064000NULL2020-11-20
5Rohan205800042024-02-05
6Isha3061000NULL2022-09-12
7Arjun206400042023-07-30
8ZoyaNULL52000NULL2024-05-01

departments

dept_iddept_name
10Engineering
20Sales
30Marketing
40Finance

Examples

INNER JOIN

Only employees with a matching department. Zoya disappears, and Finance never appears.

SELECT e.name, d.dept_name
FROM employees e
INNER JOIN departments d ON e.dept_id = d.dept_id
ORDER BY e.emp_id;
Result
namedept_name
AaravEngineering
DiyaEngineering
KabirEngineering
MeeraSales
RohanSales
IshaMarketing
ArjunSales

LEFT JOIN keeps unmatched rows

Every employee is kept; Zoya gets NULL for dept_name.

SELECT e.name, d.dept_name
FROM employees e
LEFT JOIN departments d ON e.dept_id = d.dept_id
ORDER BY e.emp_id;
Result
namedept_name
AaravEngineering
DiyaEngineering
KabirEngineering
MeeraSales
RohanSales
IshaMarketing
ArjunSales
ZoyaNULL

Headcount including empty departments

Start from departments so Finance is kept, and count employee ids so it shows 0, not 1.

SELECT d.dept_name, COUNT(e.emp_id) AS employees
FROM departments d
LEFT JOIN employees e ON e.dept_id = d.dept_id
GROUP BY d.dept_name
ORDER BY employees DESC, d.dept_name;
Result
dept_nameemployees
Engineering3
Sales3
Marketing1
Finance0

Common mistakes

  • Filtering the right table in WHERE. LEFT JOIN … WHERE d.dept_name = 'Sales' removes the NULL rows, turning it into an inner join. Put such conditions in the ON clause instead.
  • COUNT(*) after a LEFT JOIN. It counts unmatched rows as 1. Count a column from the right table.
  • Join fan-out. Joining to a table with several matches per row multiplies rows, so sums and counts grow. Aggregate first in a subquery or CTE, then join.

Practise INNER JOIN vs LEFT JOIN

Interview questions that use this concept, easiest first. Each one has the step-by-step visualizer and answer checking.

  1. Users With Zero Searches

    Find registered account profiles that have never submitted a search query using an outer join.

    Easy✓ Solved
  2. Ad Click-Through Rate (CTR)

    Calculate the percentage CTR per ad campaign rounded to 2 decimals, safely handling campaigns with zero impressions.

    Easy✓ Solved
  3. Google Maps: High-Impact Local Guides

    Find verified reviewers who submitted at least 2 photo reviews in San Francisco or Mountain View.

    Easy✓ Solved
  4. Google Drive: External Sensitive File Shares

    Audit sensitive files shared with non-Google email addresses to identify potential data exposure risks.

    Easy✓ Solved
  5. Employees Earning More Than Their Managers

    Join the employee table with itself to find staff members whose salary exceeds their direct manager.

    Easy✓ Solved
  6. Customers Who Never Order

    Identify all customer records that have no matching entries in the Orders table.

    Easy✓ Solved

Questions people ask

Is LEFT JOIN the same as LEFT OUTER JOIN?
Yes. OUTER is optional; both mean the same thing in MySQL and PostgreSQL.
Does MySQL support FULL OUTER JOIN?
No. PostgreSQL does; in MySQL you combine a LEFT JOIN and a RIGHT JOIN with UNION.