What are SQL Joins?
In SQL, joins are a way of combining data from multiple tables, based on a common key between the tables. For example, you may have a table about customers and a table about sales; by using customer_id you can join information about customers and sales together. Depending on what you'd like to achieve, you'd choose the appropriate join type.
Types of joins
There are different types of joins, that retain different parts of each table. Here's a rundown, but see each part in depth throughout this post:
Join (Inner Join)
A join is sometimes referred to as an inner join. This type of join only returns rows that match the condition (i.e. their must be results on both sides)
In the spirit of being explicit as possible in your code, it can be good to write inner join every time
Left join
A left join keeps all rows from the left table, if there's no match on the right side, the values are filled with nulls
Right join
The opposite of a left join, retains all rows from the right table, and if there's no matches on the left side, fills with nulls.
For legibility in long queries or models, it can often be best to just flip your tables around and use left joins throughout
Full join
Returns all rows from both tables, and fills blanks in with nulls.
Cross join
Returns all possible combinations of rows
Cross joins can often risk returning very large cartesian products. It's worth really considering if this type of join matches your use case
Left join example
A left join keeps all rows from the left table, if there's no match on the right side, the values are filled with nulls. You might use a left join when it's important to keep rows even if they don't have a match. For example, if you wanted a list of all birds, even if you haven't spotted them yet
SELECT
b.bird_name,
b.color,
s.location
FROM Birds b
LEFT JOIN Sightings s
ON b.bird_id = s.bird_id
ORDER BY b.bird_id;
Left table - birds
| bird_id | bird_name | color |
|---|---|---|
| 1 | Sparrow | Brown |
| 2 | Robin | Red |
| 3 | Blue Jay | Blue |
| 4 | Crow | Black |
Right table - sightings
| sighting_id | bird_id | location |
|---|---|---|
| 101 | 1 | Park |
| 102 | 2 | Garden |
| 103 | 2 | Forest |
| 104 | 4 | Parking Lot |
Left join output
| bird_name | color | location |
|---|---|---|
| Sparrow | Brown | Park |
| Robin | Red | Garden |
| Robin | Red | Forest |
| Blue Jay | Blue | NULL |
| Crow | Black | Parking Lot |
Full join example
A full join returns all rows from both tables, filling in NULL for missing matches on either side. You might use a full join when you want a complete picture of both datasets, even if some items don’t have matches. For example, if we logged sightings of birds - but we're not sure what the bird was.
SELECT
b.bird_name,
b.color,
s.location
FROM Birds b
FULL JOIN Sightings s
ON b.bird_id = s.bird_id
Left table (as before)
| bird_id | bird_name | color |
|---|---|---|
| 1 | Sparrow | Brown |
| 2 | Robin | Red |
| 3 | Blue Jay | Blue |
| 4 | Crow | Black |
Right table
New sighting, null bird_id
| sighting_id | bird_id | location |
|---|---|---|
| 101 | 1 | Park |
| 102 | 2 | Garden |
| 103 | 2 | Forest |
| 104 | 4 | Parking Lot |
| 105 | null | Zoo |
Output
| bird_name | color | location |
|---|---|---|
| Sparrow | Brown | Park |
| Robin | Red | Garden |
| Robin | Red | Forest |
| Blue Jay | Blue | NULL |
| Crow | Black | Parking Lot |
| NULL | NULL | Zoo |
Cross join example
A cross join returns all possible combinations of rows from both tables. This is useful when you want to pair every row from one table with every row from another, but be careful—this can result in a very large number of rows if your tables are big.
For example, with 4 birds and 4 sightings, you'll get 16 rows; this grows quickly.
SELECT
b.bird_name,
b.color,
s.location
FROM Birds b
CROSS JOIN Sightings s
ORDER BY b.bird_name, s.location;
Left table - birds
| bird_id | bird_name | color |
|---|---|---|
| 1 | Sparrow | Brown |
| 2 | Robin | Red |
| 3 | Blue Jay | Blue |
| 4 | Crow | Black |
Right table - sightings
| sighting_id | bird_id | location |
|---|---|---|
| 101 | 1 | Park |
| 102 | 2 | Garden |
| 103 | 2 | Forest |
| 104 | 4 | Parking Lot |
Cross join output (partial)
| bird_name | color | location |
|---|---|---|
| Sparrow | Brown | Park |
| Sparrow | Brown | Garden |
| Sparrow | Brown | Forest |
| Sparrow | Brown | Parking Lot |
| Robin | Red | Park |
| Robin | Red | Garden |
| Robin | Red | Forest |
| Robin | Red | Parking Lot |
| Blue Jay | Blue | Park |
| Blue Jay | Blue | Garden |
| Blue Jay | Blue | Forest |
| Blue Jay | Blue | Parking Lot |
| Crow | Black | Park |
| Crow | Black | Garden |
| Crow | Black | Forest |
| Crow | Black | Parking Lot |