Sample Data Used Throughout This Guide
INNER JOIN
INNER JOIN returns rows where there is a match in BOTH tables. Non-matching rows from either table are excluded.
INNER JOIN is the Default
Writing just "JOIN" in SQL means INNER JOIN. They are identical. Most developers write "JOIN" for brevity; "INNER JOIN" is more explicit and readable in complex queries.
LEFT JOIN (LEFT OUTER JOIN)
LEFT JOIN returns ALL rows from the left table, plus matched rows from the right table. Where there is no match, right table columns are NULL.
RIGHT JOIN (RIGHT OUTER JOIN)
RIGHT JOIN returns ALL rows from the right table, plus matched rows from the left table. Where there is no match, left table columns are NULL. Right JOIN is the mirror of LEFT JOIN.
Prefer LEFT JOIN over RIGHT JOIN
RIGHT JOIN is the least commonly used JOIN. Most SQL developers prefer to rewrite RIGHT JOINs as LEFT JOINs by swapping the table order — it is easier to read and reason about when the "primary" table is always on the left.
FULL OUTER JOIN
FULL OUTER JOIN returns ALL rows from BOTH tables. Where there is no match on either side, NULLs fill the missing columns.
CROSS JOIN
CROSS JOIN returns the Cartesian product — every combination of rows from both tables. No ON condition.
SELF JOIN
A SELF JOIN joins a table to itself. Used for hierarchical or comparative data within the same table.
JOIN Types Summary
| JOIN Type | Returns | NULLs for | Common Use Case |
|---|---|---|---|
| INNER JOIN | Matching rows only | None | Get related data from both tables |
| LEFT JOIN | All left + matched right | Unmatched right rows | All records + optional related data |
| RIGHT JOIN | All right + matched left | Unmatched left rows | Rarely used — rewrite as LEFT JOIN |
| FULL OUTER JOIN | All rows from both | Unmatched from either side | Find unmatched records on either side |
| CROSS JOIN | Cartesian product | None | Generate all combinations |
| SELF JOIN | Table joined to itself | Depends on JOIN type | Hierarchies, comparisons within one table |
Always Index Your JOIN Columns
The most common performance problem with JOINs is missing indexes on the ON condition columns. Always index foreign key columns and any column used in a JOIN condition. Run EXPLAIN before and after adding indexes to verify the query plan changes from Seq Scan to Index Scan.
How We Research and Update This Guide
We test the underlying formula or workflow, compare outputs with reliable references, and revise examples whenever the page content changes.
- The workflow or formula is tested directly in the tool and compared against independent reference examples.
- Examples are kept practical so readers can verify the result without hidden assumptions.
- Pages are revised whenever the interface, calculation flow, or surrounding guidance materially changes.
Frequently Asked Questions — SQL JOINs
INNER JOIN returns only the rows where there is a match in BOTH tables. If a row in the left table has no matching row in the right table, it is excluded. LEFT JOIN (LEFT OUTER JOIN) returns ALL rows from the left table, plus matched rows from the right table. Where there is no match in the right table, NULL values are returned for the right table columns. Use LEFT JOIN when you want all records from the primary table regardless of whether they have related records.
NULL appears in LEFT JOIN results for right-table columns when there is no matching row. For example: SELECT customers.name, orders.id FROM customers LEFT JOIN orders ON customers.id = orders.customer_id — customers who have never placed an order will appear with NULL in the orders.id column. This is the key use case for LEFT JOIN: finding records that DO NOT have a match (WHERE orders.id IS NULL gives you customers with no orders).
FULL OUTER JOIN returns all rows from BOTH tables, with NULLs where there is no match on either side. It combines LEFT JOIN and RIGHT JOIN. UNION combines the result sets of two SELECT queries by stacking rows (not columns). FULL OUTER JOIN joins side-by-side on a key; UNION stacks results vertically. MySQL does not support FULL OUTER JOIN natively — simulate it with LEFT JOIN UNION RIGHT JOIN.
JOINs can be slow when joining large tables without indexes on the join columns. Always index the columns in ON conditions and foreign key columns. The query planner chooses a join algorithm (Nested Loop, Hash Join, Merge Join) based on table size and available indexes. Multiple JOINs compound: a query joining 5 large tables without indexes can be extremely slow. Use EXPLAIN to see the join strategy and look for sequential scans that should be index scans.
A CROSS JOIN returns the Cartesian product — every combination of rows from both tables. If table A has 100 rows and table B has 50 rows, the result has 5,000 rows. Use cases: generating all possible combinations (e.g. all colour/size combinations for a product), populating a calendar table by crossing dates with hours, or generating test data. CROSS JOIN has no ON condition. Be careful with large tables — a CROSS JOIN on two million-row tables produces a trillion rows.
JOINs are generally faster than correlated subqueries because the query planner can optimise JOIN execution. Use JOINs when combining columns from multiple tables in SELECT results. Use subqueries when filtering based on aggregate or existence: WHERE EXISTS (subquery) or WHERE id IN (subquery). For checking existence, EXISTS is often faster than IN for large subqueries. Modern query planners often rewrite subqueries as JOINs anyway — but explicit JOINs are clearer and more predictable.