LambdaLabTM
Databases & SQL · Class 12 · Working with Two Tables
MySQLjoins⏱️ 10 min read

Equi-Join

The cartesian product made every possible pairing, most of them nonsense. An equi-join keeps only the pairings that are true — and it does it with a tool you already have: a where clause.

1The two tables

subjects records which teacher takes each subject, by storing the teacher's id rather than their name:

subjects
codesnameid
CS083Computer Science2
MA041Mathematics3
PH042Physics9
EN301English4
HI302HindiNULL
teachers (part of it)
idnamedesignation
2Mohan DasPGT
3Tashi BhutiaTGT
4Reena GuptaTGT
9Rajesh KumarPGT

The id in subjects is a foreign key pointing at the id in teachers. That shared value is the thread the join pulls on.

2The join condition

Name both tables, then add a where saying which pairings to keep: the ones where the two ids are equal.

MySQL command line client
mysql> select subjects.code, subjects.sname, teachers.name, teachers.designation from subjects, teachers where subjects.id = teachers.id;
+-------+------------------+--------------+-------------+
| code | sname | name | designation |
+-------+------------------+--------------+-------------+
| CS083 | Computer Science | Mohan Das | PGT |
| EN301 | English | Reena Gupta | TGT |
| MA041 | Mathematics | Tashi Bhutia | TGT |
| PH042 | Physics | Rajesh Kumar | PGT |
+-------+------------------+--------------+-------------+
4 rows in set (0.00 sec)

Four rows, each of them true: Computer Science really is taught by Mohan Das. The sixty meaningless pairings from the cartesian product are gone, cut down by one condition.

An equi-join keeps the rows of a cartesian product where two columns are equal.

“Equi” because the condition uses =.

Switch between the three modes below and watch the same twenty pairings be cut down to four.

Build the join yourself

Every row of one table is paired with every row of the other first — the condition is what removes the nonsense afterwards.

mysql> select * from subjects, teachers where subjects.id = teachers.id;
subjects
codesnameid
CS083Computer Science2
MA041Mathematics3
PH042Physics9
EN301English4
HI302HindiNULL
teachers (4 of the 12, so they fit)
idnamedesignation
2Mohan DasPGT
3Tashi BhutiaTGT
4Reena GuptaTGT
9Rajesh KumarPGT

5 subjects × 4 teachers. Press Pair them up to see what the database actually builds.

where subjects.id = teachers.id keeps only the pairings where the two tables agree. Hindi has NULL for its teacher, and NULL equals nothing — not even NULL — so it never matches and disappears from the answer.

3Why the column names carry a table name

Both tables have a column called id. Writing where id = id would be meaningless — MySQL cannot tell which is which. So a column is written as table.column:

ambiguous
where id = id
clear
where subjects.id = teachers.id

Columns that exist in only one of the tables — sname, designation — do not strictly need the prefix, but writing it everywhere makes the query easier to read.

4Shortening it with table aliases

Repeating subjects. and teachers. gets tiring. Give each table a short alias just after its name, and use that instead:

MySQL command line client
mysql> select s.code, s.sname, t.name from subjects s, teachers t where s.id = t.id;
+-------+------------------+--------------+
| code | sname | name |
+-------+------------------+--------------+
| CS083 | Computer Science | Mohan Das |
| EN301 | English | Reena Gupta |
| MA041 | Mathematics | Tashi Bhutia |
| PH042 | Physics | Rajesh Kumar |
+-------+------------------+--------------+
4 rows in set (0.00 sec)

Same four rows, far less typing. This is the column alias idea from the SELECT chapter, applied to a table instead.

5The other way to write it: JOIN … ON

The query above joined the tables by naming them both after from and putting the condition in the where. SQL has a second spelling that says “join” out loud and gives the condition its own keyword, on:

MySQL command line client
mysql> select s.code, s.sname, t.name from subjects s join teachers t on s.id = t.id;
+-------+------------------+--------------+
| code | sname | name |
+-------+------------------+--------------+
| CS083 | Computer Science | Mohan Das |
| EN301 | English | Reena Gupta |
| MA041 | Mathematics | Tashi Bhutia |
| PH042 | Physics | Rajesh Kumar |
+-------+------------------+--------------+
4 rows in set (0.00 sec)

The same four rows — not similar, identical, because it is the same join asked for in different words.

comma and where
from subjects s, teachers t
where s.id = t.id
join and on
from subjects s join teachers t
on s.id = t.id

You may also see inner join written in full. It is the same thing again — join on its own means an inner join:

MySQL command line client
mysql> select s.code, s.sname, t.name from subjects s inner join teachers t on s.id = t.id;
+-------+------------------+--------------+
| code | sname | name |
+-------+------------------+--------------+
| CS083 | Computer Science | Mohan Das |
| EN301 | English | Reena Gupta |
| MA041 | Mathematics | Tashi Bhutia |
| PH042 | Physics | Rajesh Kumar |
+-------+------------------+--------------+
4 rows in set (0.00 sec)

The one real advantage of this form shows up when you want to filter as well as join. The on holds the link between the tables and the where holds everything else, so the two jobs stay visibly separate:

MySQL command line client
mysql> select s.code, s.sname, t.name from subjects s join teachers t on s.id = t.id where t.designation = 'PGT';
+-------+------------------+--------------+
| code | sname | name |
+-------+------------------+--------------+
| CS083 | Computer Science | Mohan Das |
| PH042 | Physics | Rajesh Kumar |
+-------+------------------+--------------+
2 rows in set (0.00 sec)

Two of the four, because only two of those teachers are PGTs. Written the other way, the link and the filter would sit side by side in one where, joined by and — which also works, and is harder to read as the query grows.

Use whichever you are comfortable with
Both forms are correct SQL, both give identical results, and both are accepted in an exam. The comma-and-where form is the one the CBSE syllabus means when it says equi-join, and the one the class notes use, so it is what you will most often meet in a question paper. join … on is the more modern standard form and the one you will see outside school. Pick the one you can write correctly under pressure — and stay with it, rather than mixing the two halfway through a query.

6What quietly gets left out

subjects has five rows but the join returned four. Hindi is missing, because its id is NULL — no teacher has been assigned — and NULL is not equal to anything, not even to another NULL.

An equi-join only shows matches
A row on either side with no partner simply does not appear. Hindi has no teacher, so Hindi vanishes; a teacher who takes no subject vanishes too. If a join returns fewer rows than you expected, unmatched or NULL keys are the first thing to check.

7Writing a join, in three steps

1
Which tables?

Put both after from, separated by a comma. Give each a short alias.

2
What links them?

Find the shared value — nearly always a foreign key and a primary key. That is your where.

3
Which columns?

Now choose what to show, prefixing each with its table.

Extra conditions go on with and, exactly as anywhere else: where s.id = t.id and t.designation = 'PGT' gives the subjects taught by PGTs only.

8Recap

from a, b where a.k = b.k

The equi-join: keep the pairings where the keys are equal.

from a join b on a.k = b.k

The same join in the modern spelling — inner join means the same. Use whichever you prefer.

table.column

Needed whenever both tables share a column name.

from subjects s

A table alias, to keep the query short.

Unmatched rows vanish

A NULL or unmatched key means the row does not appear at all.

Quick Check

What turns a cartesian product into an equi-join?

Quick Check

Why write subjects.id rather than just id?

Quick Check

subjects has 5 rows but the equi-join returns 4. Why?

Quick Check

How do these two compare? from subjects s, teachers t where s.id = t.id · from subjects s join teachers t on s.id = t.id

Quick Check

Using join … on, where does an extra filter such as designation = 'PGT' most naturally go?