PHP Lekcije - Lekcija 3.6 - Rad sa MySQL bazom podataka. Tipovi JOIN operatora.
U MySQL se upiti sa JOIN operatorom mogu praviti na različite načine. Pokušaćemo da razmotrimo sve ove vrste upita. Evo spiska svih upita koji uključuju JOIN:
- INNER JOIN
- LEFT JOIN
- LEFT JOIN bez preseka sa desnom tabelom
- RIGHT JOIN
- RIGHT JOIN bez preseka sa levom tabelom
- FULL OUTER
- FULL OUTER gde je leva ili desna tabela prazna
Evo ilustracije za ove vrste JOIN-a:
Priložiću uz članak fajlove sa našeg sajta, među kojima će biti i join.php u kojem ću prikazivati sve zapise pomoću različitih JOIN operatora.
INNER JOIN
Počećemo sa ovim operatorom INNER JOIN, jer se ovaj operator koristi podrazumevano ako u upitu napišete samo JOIN. Ovaj operator bira sve zapise iz dve tabele gde je uslov nakon ON operatora ispunjen. Imamo dve tabele Files i Messages:
Tabela Messages:
mid | bodytext | fid |
1 | Test | NULL |
2 | Hi | 2 |
3 | Hello | NULL |
Tabela Files:
fid | path |
1 | /files/1.png |
2 | /files/2.png |
3 | /files/3.png |
Upit sa JOIN biće sledeći:
SELECT * FROM Messages INNER JOIN Files ON Messages.fid=Files.fid
Kao rezultat dobićemo sledeće zapise
mid | bodytext | fid | path |
2 | Hi | 2 | /files/2.png |
To znači da će MySQL prikazati one redove gde se vrednosti fid poklapaju.
LEFT JOIN
Kod LEFT JOIN prikazujemo sve zapise iz leve tabele (u našem slučaju Messages), uključujući i one zapise gde te vrednosti fid postoje u tabeli Files.
Tabela Messages:
mid | bodytext | fid |
1 | Test | 2 |
2 | Hi | NULL |
3 | Hello | 3 |
Tabela Files:
fid | path |
1 | /files/1.png |
2 | /files/2.png |
3 | /files/3.png |
Upit sa LEFT JOIN biće sledeći:
SELECT * FROM Messages LEFT JOIN Files ON Messages.fid=Files.fid
Kao rezultat dobićemo sledeće zapise
mid | bodytext | fid | path |
1 | Test | 2 | /files/2.png |
2 | Hi | NULL | NULL |
3 | Hello | 3 | /files/3.png |
LEFT JOIN je koristan kada želimo da prikažemo sve zapise poruka, a da proverimo kroz PHP da li postoji ili ne postoji prikačeni fajl.
LEFT JOIN bez preseka sa desnom tabelom
LEFT JOIN prikazuje sve zapise iz leve tabele, osim onih gde se fid poklapa sa fid u desnoj tabeli.
Tabela Messages:
mid | bodytext | fid |
1 | Test | 2 |
2 | Hi | NULL |
3 | Hello | 3 |
Tabela Files:
fid | path |
1 | /files/1.png |
2 | /files/2.png |
3 | /files/3.png |
Upit sa LEFT JOIN bez preseka biće sledeći:
SELECT * FROM Messages LEFT JOIN Files ON Messages.fid=Files.fid WHERE Files.fid IS NULL
Kao rezultat dobićemo sledeću selekciju:
mid | bodytext | fid | path |
2 | Hi | NULL | NULL |
LEFT JOIN bez preseka koristi se kada želimo da prikažemo sve zapise bez prikačenih fajlova.
RIGHT JOIN
RIGHT JOIN prikazuje sve zapise iz desne tabele, a ako postoje preklapanja, prikazuje i podatke iz leve tabele.
Tabela Messages:
mid | bodytext | fid |
1 | Test | 2 |
2 | Hi | NULL |
3 | Hello | 3 |
Tabela Files:
fid | path |
1 | /files/1.png |
2 | /files/2.png |
3 | /files/3.png |
Upit sa RIGHT JOIN biće sledeći:
SELECT * FROM Messages RIGHT JOIN Files ON Messages.fid=Files.fid
Kao rezultat dobićemo sledeću selekciju:
mid | bodytext | fid | path |
NULL | NULL | 1 | /files/1.png |
1 | Test | 2 | /files/2.png |
3 | Hello | 3 | /files/3.png |
RIGHT JOIN je koristan kada želimo da prikažemo sve prikačene fajlove, bez obzira da li se koriste ili ne, jednostavno sve fajlove.
RIGHT JOIN bez preseka
RIGHT JOIN bez preseka prikazuje sve zapise iz desne tabele, osim onih gde postoji presek sa levom tabelom.
Tabela Messages:
mid | bodytext | fid |
1 | Test | 2 |
2 | Hi | NULL |
3 | Hello | 3 |
Tabela Files:
fid | path |
1 | /files/1.png |
2 | /files/2.png |
3 | /files/3.png |
Upit sa RIGHT JOIN bez preseka biće sledeći:
SELECT * FROM Messages RIGHT JOIN Files ON Messages.fid=Files.fid WHERE Messages.fid IS NULL
Na ovaj način dobićemo sledeće podatke:
mid | bodytext | fid | path |
NULL | NULL | 1 | /files/1.png |
RIGHT JOIN je koristan kada želimo da prikažemo sve prikačene fajlove koji nisu prikačeni ni na jednu poruku. Na primer, ako želimo da prikažemo fajlove koji se ne koriste.
FULL OUTER JOIN
Iako u SQL jeziku postoji FULL OUTER JOIN, u MySQL ovaj operator ne postoji. Razlog je što takav operator predstavlja veliki teret za server. Sada imamo 3 fajla i 3 poruke, a rezultat izvršenja upita daje 4 reda. Nisam siguran da je dobra ideja pisati upit koji kombinuje dva upita LEFT JOIN i RIGHT JOIN. Ipak, postoji mogućnost da se emulira FULL OUTER JOIN upit.
Tabela Messages:
mid | bodytext | fid |
1 | Test | 2 |
2 | Hi | NULL |
3 | Hello | 3 |
Tabela Files:
fid | path |
1 | /files/1.png |
2 | /files/2.png |
3 | /files/3.png |
Emulacija FULL OUTER JOIN upita bi bila sledeća:
SELECT * FROM Messages LEFT JOIN Files ON Messages.fid = Files.fid UNION SELECT * FROM Messages RIGHT JOIN Files ON Messages.fid = Files.fid
U ovom upitu koristimo UNION operator da bismo spojili dva upita: LEFT JOIN i RIGHT JOIN.
Kao rezultat dobićemo sledeće zapise:
mid | bodytext | fid | path |
1 | Test | 2 | /files/2.png |
2 | Hi | NULL | NULL |
3 | Hello | 3 | /files/3.png |
NULL | NULL | 1 | /files/1.png |
Ovde već ne mogu da kažem zašto bi FULL OUTER JOIN bio potreban. Ali pošto postoji u SQL-u, verovatno će nekada zatrebati.
FULL OUTER JOIN bez preseka
Još jedna vrsta JOIN-a je još “luđa” od samog FULL OUTER JOIN-a, a to je FULL OUTER JOIN bez preseka. Ne mogu ni da zamislim gde bi se ova vrsta JOIN-a koristila. Rezultat daje fajlove koji se ne koriste i poruke bez fajlova. Kao što ste verovatno već pretpostavili, ni ovaj operator ne postoji u MySQL-u. Ostaje samo da se emulira pomoću dva operatora: LEFT JOIN bez preseka i RIGHT JOIN bez preseka.
Emulacija FULL OUTER JOIN bez preseka:
$sql = 'SELECT * FROM Messages LEFT JOIN Files ON Messages.fid = Files.fid WHERE Files.fid IS NULL UNION SELECT * FROM Messages RIGHT JOIN Files ON Messages.fid = Files.fid WHERE Messages.fid IS NULL';
Kao rezultat (izvorne tabele su iste kao u primeru sa FULL OUTER JOIN) dobićemo:
mid | bodytext | fid | path |
2 | Hi | NULL | NULL |
NULL | NULL | 1 | /files/1.png |
Verovatno je to sve, u narednim lekcijama počećemo da pišemo još složenije upite za više tabela odjednom.