🔍 Ctrl+K
🟢 Easy

Sample Tables — Simple Data

All JOIN examples below use these two tiny tables so you can see exactly what each JOIN returns. Keep them in mind — every output table is derived from these rows.

employees

employee_idfirst_namedepartment_idsalary
101Alice1070000
102Bob2080000
103Charlie1075000
104DavidNULL60000

Note: David has no department (NULL).

Venn view — left = employees (4) • right = departments (3) INNER only overlap LEFT all left + match RIGHT all right + match FULL OUTER all rows

Visual: How INNER, LEFT, RIGHT and FULL OUTER JOINs relate — keep the 4×3 sample tables in mind.

departments

department_iddepartment_name
10HR
20Engineering
30Marketing

Note: Marketing (30) has no employees.

How to read
Left table = employees (4 rows), Right table = departments (3 rows). Every JOIN below shows which rows survive and what the 4 output rows look like.
🟢 Easy

Why JOIN?

Real databases separate data into related tables. JOIN brings them together.

Employees → Departments
employees.department_id → departments.department_id
🟢 Easy

INNER JOIN

INNER JOIN returns only rows where the join condition matches in both tables.

SQL
SELECT e.first_name, d.department_name
FROM employees e
INNER JOIN departments d
    ON e.department_id = d.department_id;
INNER JOIN — Only Matching Rows (3 rows) Alice+HR • Bob+Engineering • Charlie+HR — David & Marketing excluded employees ⨝ departments on department_id

Expected Output (only matching rows)

first_namedepartment_name
AliceHR
BobEngineering
CharlieHR

David (NULL dept) and Marketing (30, no employees) are excluded. 3 rows.

Returns matching records only.

🟡 Intermediate

LEFT JOIN

LEFT JOIN returns all rows from the left table and matching rows from the right, filling missing matches with NULLs.

SQL
SELECT d.department_name, e.first_name
FROM departments d
LEFT JOIN employees e
    ON d.department_id = e.department_id;

Expected Output (all departments)

department_namefirst_name
HRAlice
HRCharlie
EngineeringBob
MarketingNULL

Marketing has no match → first_name is NULL. David not shown because query starts from departments.

All departments, including those with no employees.

🟢 Easy

RIGHT JOIN

RIGHT JOIN returns all rows from the right table and matching rows from the left, the mirror of LEFT JOIN.

SQL
SELECT e.first_name, d.department_name
FROM employees e
RIGHT JOIN departments d
    ON e.department_id = d.department_id;

Expected Output (all employees)

first_namedepartment_name
AliceHR
BobEngineering
CharlieHR
DavidNULL

David (NULL dept) appears with NULL department_name. Marketing not shown.

🟡 Intermediate

FULL OUTER JOIN

FULL OUTER JOIN returns all rows from both tables, matching where possible and filling gaps with NULLs on either side.

SQL
SELECT e.first_name, d.department_name
FROM employees e
FULL OUTER JOIN departments d
    ON e.department_id = d.department_id;

Expected Output (everyone)

first_namedepartment_name
AliceHR
BobEngineering
CharlieHR
DavidNULL
NULLMarketing

5 rows: 3 matches + 1 unmatched employee + 1 unmatched department.

MySQL has no native FULL OUTER JOIN — use UNION of LEFT and RIGHT.

🔴 Advanced

SELF JOIN

SELF JOIN joins a table to itself, treating the same table as two logical copies — essential for employee-manager hierarchies.

SQL
SELECT e.first_name AS employee, m.first_name AS manager
FROM employees e
LEFT JOIN employees m
    ON e.manager_id = m.employee_id;

Sample: employees as e and m (manager)

employeemanager
Alice (101)— (manager NULL)
Bob (102)Alice
Charlie (103)Alice
David (104)Bob

Uses e.manager_id = m.employee_id with table aliases e (employee) and m (manager).

Same table as two logical copies (e and m).

🟡 Intermediate

CROSS JOIN

CROSS JOIN produces the Cartesian product, combining every row from one table with every row from the other table.

SQL
SELECT a.team_name AS team_a, b.team_name AS team_b
FROM teams a
CROSS JOIN teams b;

Expected: Cartesian Product

With 4 employees × 3 departments = 12 rows (every combination). Example first 3 rows:

first_namedepartment_name
AliceHR
AliceEngineering
AliceMarketing

… 9 more rows (rarely used alone — usually with filtering).

4 × 5 = 20 rows — every combination.

🔴 Advanced

Employee Earning More Than Manager

This classic interview problem finds employees who earn more than their manager by self-joining the employees table on manager_id.

SQL
SELECT e.first_name AS employee_name, e.salary, m.first_name AS manager_name, m.salary
FROM employees e
JOIN employees m
    ON e.manager_id = m.employee_id
WHERE e.salary > m.salary;

Expected Output (employees earning more than manager)

employee_nameemployee_salarymanager_namemanager_salary
Bob80000Alice70000
Charlie75000Alice70000

David not shown (manager is Bob, 80000 > 60000 false). Alice has no manager.

Key: e.manager_id = m.employee_id

🟡 Intermediate

Multi-Table JOIN

Multi-table JOIN connects more than two tables in sequence, following relationships from employees to departments to jobs.

SQL
SELECT e.first_name, d.department_name, j.job_title
FROM employees e
JOIN departments d ON e.department_id = d.department_id
JOIN jobs j ON e.job_id = j.job_id;

Expected Output (three tables joined)

first_namedepartment_namejob_title
AliceHREngineer
BobEngineeringManager
CharlieHRAnalyst

David excluded (no department). Marketing excluded (no employee).