SQL Fundamentals - Part Three (JOIN)
- How to retrieve data from several tables?
- The solution is to use table joins (γγΌγγ«η΅ε)
- Scary, but very important: since a lot of the times in prod, data is stored between multiple tables
- Know the difference between
INNER JOIN/OUTER JOIN
In the future, when civilizations will live between several planets of the Solar System and exchange overwhelming amounts of data between each other, you won't be able to survive without knowing SQL.
We will work with those tables
table name: martians
|id |name |
|:-:|:------------:|
|1 |γγͺγΌ |
|2 |γγΌγγ€γͺγγΌ|
|3 |γγ³ |
|4 |γγ³γγ«γγ’ |
|5 |γ΄γ©γ«γγ’γΌγ|
table name: histories
|id |martians_id|planet|
|:-:|:---------:|:----:|
|1 |3 |ε°η |
|2 |1 |ζ¨ζ |
|3 |4 |εζ |
|4 |5 |ζ΅·ηζ|
INNER JOIN: Assemble two tables into one
- Use table aliases (
AS m,AS h) to keep it classy.
SELECT *
FROM martians
AS m
INNER JOIN "histories" AS h
ON m.id = h.martians_id;
| id | name | id | martians_id | planet |
|---|---|---|---|---|
| 1 | γγͺγΌ | 2 | 1 | ζ¨ζ |
| 3 | γγ³ | 1 | 3 | ε°η |
| 4 | γγ³γγ«γγ’ | 3 | 4 | εζ |
| 5 | γ΄γ©γ«γγ’γΌγ | 4 | 5 | ζ΅·ηζ |
Using SELECT, only keep the columns you need
SELECT m.name, h.planet
FROM martians
AS m
INNER JOIN "histories" AS h
ON m.id = h.martians_id;
| m.name | h.planet |
|---|---|
| γγͺγΌ | ζ¨ζ |
| γγ³ | ε°η |
| γγ³γγ«γγ’ | εζ |
| γ΄γ©γ«γγ’γΌγ | ζ΅·ηζ |
If your actual column names include uppercase, spaces, or non-ASCII characters: wrap them in "quotes" to avoid the wrath of PostgreSQL.
SELECT m."εε", h."ζζ"
LEFT OUTER JOIN
Beware: when performing a JOIN operation, unmatching records will dissapear.
This is what you should do instead:
SELECT m.name, h.planet
FROM martians
AS m
LEFT OUTER JOIN "histories" AS h
ON m.id = h.martians_id;
| m.name | h.planet |
|---|---|
| γγͺγΌ | ζ¨ζ |
| γγΌγγ€γͺγγΌ | NULL |
| γγ³ | ε°η |
| γγ³γγ«γγ’ | εζ |
| γ΄γ©γ«γγ’γΌγ | ζ΅·ηζ |
This will add a null value to unmatched values.
- NULL values will break WHERE conditions unless you explicitly use IS NULL.
- If your query drops records like itβs ghosting you, check your join type.
INNER JOINonly loves perfect matches.LEFT OUTER JOINaccepts everyone, even if theyβre broken (NULLs and all). - In a real environment,
INNER JOINis used more often to avoid querying noise and null values.
RIGHT OUTER JOIN
Return all rows from the right table, and the matching rows from the left. If there's no match, left table values become NULL.
SELECT m.name, h.planet
FROM martians
AS m
RIGHT OUTER JOIN "histories" AS h
ON m.id = h.martians_id;
| m.name | h.planet |
|---|---|
| γγͺγΌ | ζ¨ζ |
| γγ³ | ε°η |
| γγ³γγ«γγ’ | εζ |
| γ΄γ©γ«γγ’γΌγ | ζ΅·ηζ |
In this example, it gives the same result as INNER JOIN because all martians_id values match an existing martian.
To really see the effect of RIGHT OUTER JOIN, youβd need a record in "histories" with a martians_id that doesnβt exist in "martians".
FULL OUTER JOIN
Return all rows from both tables, matching where possible, and filling in NULL where not.
SELECT m.name, h.planet
FROM martians
AS m
FULL OUTER JOIN "histories" AS h
ON m.id = h.martians_id;
| m.name | h.planet |
|---|---|
| γγͺγΌ | ζ¨ζ |
| γγΌγγ€γͺγγΌ | NULL |
| γγ³ | ε°η |
| γγ³γγ«γγ’ | εζ |
| γ΄γ©γ«γγ’γΌγ | ζ΅·ηζ |
This behaves exactly like LEFT OUTER JOIN here because histories doesnβt contain any records without a matching martians_id. Add a rogue one to see NULL in m.name.
π‘ JOIN ORACLE SAYS:
INNER JOIN: only love with conditions.LEFT OUTER JOIN: keeps left table's ghosts.RIGHT OUTER JOIN: brings right tableβs strays.FULL OUTER JOIN: a big weird family reunion where nobodyβs left out.