Eksempel med tabel A og B:
A (forælder) B (barn) ==========================id | navn pid | navn ------------ ------------ 1 | Alex 1 | Kate 2 | Bill 1 | Lia 3 | Cath 3 | Mary 4 | Dale NULL | Pan 5 | Evan
Hvis du vil finde forældre og deres børn, laver du en INNER JOIN
:
VÆLG id, forælder.navn SOM forælder , pid, barn.navn SOM barnFRA forælder INNER JOIN barn PÅ parent.id =barn.pid
Resultatet er, at hvert match af en forælder
s id
fra den venstre tabel og et underordnet
s pid
fra den anden tabel vises som en række i resultatet:
+----+--------+------+-------+| id | forælder | pid | barn | +----+--------+------+-------+| 1 | Alex | 1 | Kate || 1 | Alex | 1 | Lia || 3 | Cath | 3 | Mary |+----+--------+------+------+
Nu viser ovenstående ikke forældre uden børn (fordi deres id'er ikke har et match i barnets id'er, så hvad gør du? Du laver en ydre joinforbindelse i stedet for. Der er tre typer af outer joins, den venstre, den højre og den fulde ydre joinforbindelse. Vi skal bruge den venstre, da vi vil have de "ekstra" rækker fra den venstre tabel (forælder):
VÆLG id, forælder.navn SOM forælder , pid, barn.navn SOM barnFRA forælder VENSTRE JOIN barn PÅ parent.id =barn.pid
Resultatet er, at udover tidligere kampe, vises alle forældre, der ikke har et match (læs:ikke har et barn), også:
+----+--------+------+-------+| id | forælder | pid | barn | +----+--------+------+-------+| 1 | Alex | 1 | Kate || 1 | Alex | 1 | Lia || 3 | Cath | 3 | Mary || 2 | Bill | NULL | NULL || 4 | Dale | NULL | NULL || 5 | Evan | NULL | NULL |+----+--------+------+------+
Hvor blev alle de NULL
kommer fra? Nå, MySQL (eller ethvert andet RDBMS, du måtte bruge) ved ikke, hvad de skal placere der, da disse forældre ikke har noget match (barn), så der er ingen pid
heller ikke barn.navn
at matche med de forældre. Så den sætter denne specielle ikke-værdi kaldet NULL
.
Min pointe er, at disse NULLs
oprettes (i resultatsættet) under LEFT OUTER JOIN
.
Så hvis vi kun vil vise de forældre, der IKKE har et barn, kan vi tilføje en WHERE child.pid IS NULL
til LEFT JOIN
over. Koden JOIN
pid
er NULL vil blive vist:
VÆLG id, forælder.navn SOM forælder , pid, barn.navn SOM barn FRA forælder VENSTRE JOIN barn PÅ parent.id =barn.pid. HVOR barn.pid ER NULL
Resultat:
+----+--------+------+-------+| id | forælder | pid | barn | +----+--------+------+-------+| 2 | Bill | NULL | NULL || 4 | Dale | NULL | NULL || 5 | Evan | NULL | NULL |+----+--------+------+------+
Hvad sker der nu, hvis vi flytter den ER NULL
tjek fra WHERE
til den tilsluttede ON
klausul?
VÆLG id, forælder.navn SOM forælder , pid, barn.navn SOM barn FRA forælder VENSTRE JOIN barn PÅ parent.id =barn.pid OG barn.pid ER NULL
I dette tilfælde forsøger databasen at finde rækker fra de to tabeller, der matcher disse betingelser. Det vil sige rækker hvor parent.id =child.pid
OG child.pid IN NULL
. Men den kan finde ingen sådan match fordi ingen child.pid
kan være lig med noget (1, 2, 3, 4 eller 5) og være NULL på samme tid!
Så betingelsen:
ON parent.id =child.pidAND child.pid ER NULL
svarer til:
ON 1 =0
som altid er False
.
Så hvorfor returnerer den ALLE rækker fra den venstre tabel? Fordi det er et LEFT JOIN! Og venstre joinforbindelse returnerer rækker, der matcher (ingen i dette tilfælde) og også rækker fra den venstre tabel, der ikke matcher checken (alt i dette tilfælde ):
+----+--------+------+-------+| id | forælder | pid | barn | +----+--------+------+-------+| 1 | Alex | NULL | NULL || 2 | Bill | NULL | NULL || 3 | Cath | NULL | NULL || 4 | Dale | NULL | NULL || 5 | Evan | NULL | NULL |+----+--------+------+------+
Jeg håber, at ovenstående forklaring er klar.
Sidenote (ikke direkte relateret til dit spørgsmål):Hvorfor i alverden panorerer
ikke dukke op i ingen af vores JOINs? Fordi hans pid
er NULL
og NULL i (ikke almindelig) logik i SQL er ikke lig med noget, så det kan ikke matche med nogen af de overordnede id'er (som er 1,2,3,4 og 5). Selvom der var en NULL der, ville den stadig ikke matche, fordi NULL
er ikke lig med noget, ikke engang NULL
sig selv (det er en meget mærkelig logik, ja!). Det er derfor, vi bruger den særlige check IS NULL
og ikke en =NULL
tjek.
Så vil Panorere
dukke op, hvis vi laver en RIGHT JOIN
? Ja, det vil! Fordi en RIGHT JOIN vil vise alle resultater, der matcher (den første INNER JOIN, vi gjorde) plus alle rækker fra RIGHT-tabellen, der ikke matcher (som i vores tilfælde er én, (NULL, 'Pan') række.
VÆLG id, forælder.navn SOM forælder , pid, barn.navn SOM barn FRA forælder HØJRE JOIN barn PÅ parent.id =barn.pid
Resultat:
+------+--------+------+-------+| id | forælder | pid | barn | +---------------+------+-------+| 1 | Alex | 1 | Kate || 1 | Alex | 1 | Lia || 3 | Cath | 3 | Mary || NULL | NULL | NULL | Panorer |+------+--------+------+-------+
Desværre har MySQL ikke FULD JOIN
. Du kan prøve det i andre RDBMS'er, og det vil vise:
+------+--------+------+-------+| id | forælder | pid | barn | +------+--------+------+------+| 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 | Panorer |+------+--------+------+-------+