PHP Join meerdere tabellen

Status
Niet open voor verdere reacties.

ClaudiaWD

Gebruiker
Lid geworden
21 jul 2011
Berichten
109
Hey,

Ik had al wat gezocht, maar kon het niet echt vinden. Ik ben momenteel met een website bezig welke nogal een complexe database zal gaan bevatten. Hierom ben ik van plan PHP join te gebruiken. Ik heb hier al verschillende artikeltjes over gelezen, maar echt begrijpen doe ik het nog niet.

Mijn databasestructuur voor het betreffende onderdeel:
============
games
============
game_id
game_name
game_description
game_genre
etc.

============
games_images
============
image_id
image_game_id
image_link
etc.

============
games_reviews
============
review_id
review_game_id
review_description
etc.

Nu heb ik met behulp van Foreign Keys bij de tabellen games_images en games_reviews de velden image_game_id en review_game_id gelinkt naar de tabel games met het veld game_id.

Nu wil ik op de website de velden game_name, image_link en review_description uitlezen waar bijv. game_id = 2. Zover ik wijzer ben geworden moet ik dit doen met een MULTIPLE JOIN. Maar hoe ik die join nou precies moet maken, dat begrijp ik niet helemaal. Kan iemand er - van uit gaande van bovenstaande tabellen - een voorbeeld voor maken?

Dat zou fijn zijn.

Meer informatie nodig? Zeg het even, dan laat ik het weten. :)

Bedankt alvast.
 
Waarom zou je willen joinen?
Naar mijn idee hebben games_images & games_reviews niet echt wat met elkaar te maken.

Het is logischer om aparte queries te maken.

Of je moet in een games overzicht willen tellen hoeveel images en/of reviews er zijn, dat is nog een beetje logisch om te joinen.
 
Hier gaat het specifiek alleen om de reviews, maar er komen straks ook achievements bij. Dit zijn 1000en lijsten en ik kan daar dan ook niet steeds overal de informatie van de games bij zetten, toch? Hoe kan ik dat dan gemakkelijk aanpakken?

Ik dacht eerlijk gezegd dat ik hiermee wel goed deed. Ook moet ik nog een vote-systeem er aan vast koppelen, welke waarschijnlijk ook in een andere database komt te staan. Dit moet ik dan toch ook linken, of niet?

Bij deze dan graag een uitleg hoe dit tactisch aan te kunnen pakken, want volgens mij doe ik het verkeerd. :p

edit. ik zit op een andere computer thuis, zo te zien is daar de standaard inlog van een familielid. vandaar dus. sorry.
 
Laatst bewerkt:
Ik denk dat je even iets verkeerd begrijpt :) Een koppeling en een JOIN zijn niet hetzelfde. De koppeling bestaat nu al namelijk, want je hebt een veld wat je kunt gebruiken om te kijken bij welk spel een plaatje, review of achievement hoort. Een JOIN daarentegen is het in een enkele query verbinden van twee tabellen om zo informatie uit twee tabellen tegelijk op te kunnen halen. Dit kun je gebruiken als je data uit de ene tabel nodig hebt om data uit de andere tabel te vinden (bijvoorbeeld: zoek alle plaatjes van het spel met de naam "Superracer", waarbij je een JOIN moet uitvoeren op games en images, zodat je alle games kunt kiezen waarbij de naam "Superracer" is en alle plaatjes die dezelfde ID hebben als dat spel)

Het is echter helemaal niet nodig (en zelfs af te raden of gewoonweg fout) om altijd alle tabellen te JOINEN die gekoppeld zijn. Vaak genoeg is het beter om gewoon een paar losse queries the doen.

Dus, als je alle info nodig hebt van game_id = 2, dan doe je gewoon 3 queries: 1 op games, 1 op images en 1 op reviews, en haal je alle data op. Ze zijn dan nog steeds gekoppeld, maar je hebt de data uit de ene tabel niet nodig om de data uit een andere tabel op te halen.

Wil je alle info van game_name = "Superracer" dan kun je nog steeds 3 queries doen, maar in de query op images en de query op reviews moet je dan een JOIN gebruiken zodat je kunt selecteren WHERE game_name = 'Superracer', omdat je het nodig hebt om de juiste rijen te vinden in de images en reviews tabel.


Ik hoop dat het een beetje duidelijk is :+ Zo niet dan moet je het maar laten weten dan probeer ik het duidelijker uit te leggen.
 
Oh, oké, oké!

Dus voor mij zelf is het nu duidelijk over welke game het gaat. Nu hoef ik slechts de query's uit te voeren en uit te lezen van de 3 tabellen?
En hoe werkt het dan als ik het met een random game wil doen?

Dus stel ik heb van een random game de bijbehorende review nodig en de image. Dan kan ik toch niet zomaar 3 verschillende query's uitvoeren, want dan pakt hij toch 3 verschillende?

Wel bedankt voor de uitleg overigens! :)
 
Als je van een random game de data wil, moet je eerst een random game nemen en dan die informatie gebruiken om de overige data te verzamelen. Dus je doet een query op games en daar pak je een random rij uit, en dan lees je na de eerste query uit welke game het is geworden, en gebruik je die data in de andere twee queries zodat ze informatie over dezelfde game ophalen.
 
En dat doe je dan simpelweg met get id, of? Ik heb het zo echt nog nooit gedaan. :o
 
Je haalt in PHP de data op na de query met mysql_fetch commando's. Heb je dat al eerder gedaan? De basis structuur is dat je eerst de query uitvoert:

PHP:
$result = mysql_query( "SELECT id, naam, veld FROM tabel_naam WHERE veld = 'waarde'" );

Wat je dan terugkrijgt is een zgn "result resource", een verwijzing die alleen bijhoudt welke query je uitgevoerd hebt. Je hebt dan nog geen informatie, maar je kunt een rij uit de query ophalen met bijv. mysql_fetch_assoc:

PHP:
$rij = mysql_fetch_assoc( $result );

Op dat moment is $rij een array met 3 velden, 'id', 'naam' en 'veld', de drie dingen die je ophaalde met je query. Je kunt dan bijv ID pakken op deze manier:

PHP:
$id = $rij['id'];

Die kun je vervolgens gebruiken om de volgende query op te halen, door de waarde van $id in de query te plakken in PHP:

PHP:
$nieuwe_query = mysql_query( "SELECT id, plaatje, naam_plaatje FROM andere_tabel WHERE koppel_id = " . $id );

En dan kun je op dezelfde manier die data ophalen.

Als je meer dan 1 rij terugkrijgt, moet je mysql_fetch_assoc meerdere keren aanroepen, bij elke aanroep krijg je 1 rij terug (en als de rijen op zijn krijg je FALSE terug)

Hoop dat je er zo uitkomt :P
 
Ja, ja, helemaal top!

Ik gebruik normaal 9/10 keer while($query=mysql_fetch_array($queryoutput){}. Ik neem aan dat dit vrij weinig uitmaakt verder? Uitsluitend met het aantal records wat je dus in feite wilt weergeven.
 
Zo'n while loop is de makkelijkste manier om alle data binnen te halen ja. Dat is een beetje de standaard.
 
Het is echter helemaal niet nodig (en zelfs af te raden of gewoonweg fout) om altijd alle tabellen te JOINEN die gekoppeld zijn. Vaak genoeg is het beter om gewoon een paar losse queries the doen.

Nu het opgelost is ben ik toch wel benieuwd naar waarom het beter is om meerdere queries te gebruiken i.p.v. een join?
 
Dat zal ik na het eten proberen uit te leggen :P Maar eerst heb ik honger.
 
Goed laat ik even een voorbeeldje doen van een situatie waarin het af te raden is om een JOIN te doen ipv twee losse queries:

Stel dat we een bank database hebben. Een persoon vult zijn rekeningnummer in en we hebben zijn naam nodig, en van elke dag sinds hij lid is van de bank willen we het saldo van zijn rekening opvragen. Als we nu 1 query gebruiken waarin we de persoons-tabel koppelen aan de rekening tabel en alle saldo's ophalen, op deze manier:
[sql]SELECT naam, saldo, datum
FROM persoon
INNER JOIN rekening ON rekening.persoon_id = persoon.id
WHERE persoon.rekeningnummer = 1234567890
[/sql]

en die persoon is al 10 jaar lid van de bank, dan halen we 3650 saldo's op, 3650 datums, en 3650 keer de naam van de rekeninghouder. Dat is dus 3649 instanties van nutteloze data, die echter wel over de lijn gezonden worden en dus performance van je database kosten. Als we echter 2 queries doen, 1 waarbij we de naam en het persoon id ophalen en 1 waarin we de saldo's en datums ophalen, dan is het niet nodig om 3649 keer onnodig een naam te verzenden naar de applicatie.

Voor een voorbeeld waarin het niet eens mogelijk is om 1 query te gebruiken, stel dat we dezelfde persoon hebben, met dezelfde saldo's, maar dit keer willen we naast zijn naam en de bedragen ook nog alle banken ophalen waar deze persoon ooit gepint heeft. Als we nu een query maken, dan krijg je zoiets:


[sql]SELECT naam, saldo, datum, locatie
FROM persoon
INNER JOIN rekening ON rekening.persoon_id = persoon.id
INNER JOIN transactie ON transactie.persoon_id = persoon.id
WHERE persoon.rekeningnummer = 1234567890
[/sql]

Misschien zie je het al, misschien zie je het nog niet... maar dit levert een gigantische lading aan nutteloze combinaties op. Het is namelijk voor de database niet mogelijk om een transactie en een saldo te koppelen, omdat die twee dingen niks met elkaar te maken hebben. Wat er dus gebeurd is dat er een carthesisch product gemaakt wordt van elke gevonden locatie met elk saldo. Stel dat we 3650 saldos hebben (van 10 jaar bij de bank) en dat deze persoon bovendien veel reist en in 100 banken geld gepakt heeft, dan krijg je 3650x100 = 365,000 rijen terug. Een voor elke mogelijk combinatie van een saldo en een bezochte locatie.

(En wederom 365,000 namen, waarvan alle behalve 1 nutteloos zijn)

Daarom is het soms beter om meerdere queries te doen ipv altijd een JOIN toe te passen. Hoop dat het duidelijk is :)
 
Ik begrijp het. Dankjewel voor de uitleg. Dan zal ik mijn eigen joins eens gaan nakijken of die dit probleem hebben.
 
Laatst bewerkt:
Ik sluit me aan bij het anti-join kamp...

Joins zijn traaaag...

Veel beter om goede key informatie via de eerste query op te halen, en dan wat details uit een andere tabel met een 2e query.

andere tips die ik voor jullie heb zijn:

- kijk eens naar database abstractie via http://adodb.sf.net, ik zweer erbij omdat het me in staat stelt ook andere RDBMS software te gebruiken dan mySQL.

- overweeg caching (kan automagisch met adodb!) via files op het php filesystem, van vaakgebruikte langdurige queries uit niet-zo-vaak-veranderende data, als je meer snelheid wilt.
 
Laatst bewerkt:
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan