Contoh dengan tabel A dan B:
A (parent) B (child)
============ =============
id | name pid | name
------------ -------------
1 | Alex 1 | Kate
2 | Bill 1 | Lia
3 | Cath 3 | Mary
4 | Dale NULL | Pan
5 | Evan
Jika Anda ingin menemukan orang tua dan anak-anak mereka, lakukan INNER JOIN
:
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent INNER JOIN child
ON parent.id = child.pid
Hasilnya adalah setiap kecocokan parent
id
dari tabel kiri dan child
pid
dari tabel kedua akan ditampilkan sebagai baris dalam hasil:
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
+----+--------+------+-------+
Sekarang, di atas tidak menunjukkan orang tua tanpa anak (karena id mereka tidak memiliki kecocokan dengan id anak, jadi apa yang Anda lakukan? Anda melakukan outer join sebagai gantinya. Ada tiga jenis outer join, kiri, kanan dan gabungan luar penuh. Kita membutuhkan yang kiri karena kita menginginkan baris "ekstra" dari tabel kiri (induk):
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent LEFT JOIN child
ON parent.id = child.pid
Hasilnya selain pertandingan sebelumnya, semua orang tua yang tidak memiliki kecocokan (baca:belum punya anak) juga ditampilkan:
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
| 2 | Bill | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
+----+--------+------+-------+
Di mana semua NULLs
. itu? berasal dari? Yah, MySQL (atau RDBMS lain yang mungkin Anda gunakan) tidak akan tahu apa yang harus diletakkan di sana karena orang tua ini tidak memiliki kecocokan (anak), jadi tidak ada pid
atau child.name
untuk mencocokkan dengan orang tua itu. Jadi, ini menempatkan non-nilai khusus yang disebut NULLs
.
Maksud saya adalah bahwa NULLs
ini dibuat (dalam kumpulan hasil) selama LEFT OUTER JOIN
.
Jadi, jika kita ingin menampilkan hanya orang tua yang TIDAK memiliki anak, kita dapat menambahkan WHERE child.pid IS NULL
ke LEFT JOIN
di atas. The WHERE
klausa dievaluasi (diperiksa) setelah JOIN
dilakukan. Jadi, jelas dari hasil di atas bahwa hanya tiga baris terakhir tempat pid
adalah NULL akan ditampilkan:
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent LEFT JOIN child
ON parent.id = child.pid
WHERE child.pid IS NULL
Hasil:
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 2 | Bill | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
+----+--------+------+-------+
Sekarang, apa yang terjadi jika kita memindahkan IS NULL
periksa dari WHERE
untuk bergabung dengan ON
klausa?
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent LEFT JOIN child
ON parent.id = child.pid
AND child.pid IS NULL
Dalam hal ini database mencoba untuk menemukan baris dari dua tabel yang cocok dengan kondisi ini. Yaitu, baris di mana parent.id = child.pid
DAN child.pid IN NULL
. Tetapi ia tidak dapat menemukan tidak ada kecocokan seperti itu karena tidak ada child.pid
bisa sama dengan sesuatu (1, 2, 3, 4 atau 5) dan NULL pada saat yang sama!
Jadi, syaratnya:
ON parent.id = child.pid
AND child.pid IS NULL
setara dengan:
ON 1 = 0
yang selalu False
.
Jadi, mengapa mengembalikan SEMUA baris dari tabel kiri? Karena ini adalah KIRI GABUNG! Dan gabungan kiri mengembalikan baris yang cocok (tidak ada dalam kasus ini) dan juga baris dari tabel kiri yang tidak cocok centang (semua dalam kasus ini ):
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 1 | Alex | NULL | NULL |
| 2 | Bill | NULL | NULL |
| 3 | Cath | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
+----+--------+------+-------+
Saya harap penjelasan di atas jelas.
Sidenote (tidak terkait langsung dengan pertanyaan Anda):Mengapa tidak Pan
muncul di salah satu GABUNG kami? Karena pid
-nya adalah NULLs
dan NULL dalam logika SQL (tidak umum) tidak sama dengan apa pun sehingga tidak dapat cocok dengan id induk mana pun (yaitu 1,2,3,4 dan 5). Bahkan jika ada NULL di sana, itu tetap tidak cocok karena NULLs
tidak sama dengan apa pun, bahkan NULLs
sendiri (itu logika yang sangat aneh, memang!). Itu sebabnya kami menggunakan cek khusus IS NULL
dan bukan = NULL
periksa.
Jadi, akankah Pan
muncul jika kita melakukan RIGHT JOIN
? Ya, tentu saja! Karena RIGHT JOIN akan menampilkan semua hasil yang cocok (INNER JOIN pertama yang kami lakukan) ditambah semua baris dari tabel RIGHT yang tidak cocok (yang dalam kasus kami adalah satu, (NULL, 'Pan')
baris.
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent RIGHT JOIN child
ON parent.id = child.pid
Hasil:
+------+--------+------+-------+
| id | parent | pid | child |
+---------------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
| NULL | NULL | NULL | Pan |
+------+--------+------+-------+
Sayangnya, MySQL tidak memiliki FULL JOIN
. Anda dapat mencobanya di RDBMS lain, dan itu akan menunjukkan:
+------+--------+------+-------+
| id | parent | pid | child |
+------+--------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
| 2 | Bill | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
| NULL | NULL | NULL | Pan |
+------+--------+------+-------+