[PHP/MySQL] 2 Tabellen koppelen [INNERJOIN]

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • RedHat
  • Registratie: Augustus 2000
  • Laatst online: 18:54
Op mijn weg om meer te leren over PHP/MySQL kom ik tegen een probleempje. Vroeger kon ik heel erg uit de voeten met PHP/MySQL maar na 2 jaar helemaal niets meer gedaan te hebben valt het vies tegen.

Het niveau van mijn vraag is dan ook al niet erg hoog, en hoop dat ik jullie kan gebruiken om te testen.
Heb de search gebruikt voor mijn vraag maar dat werkt _net_ niet voor mij op de een of andere manier. Ook heeft de search hier alleen van 2002 en terug geindexeert, erg lastig dus.

Oké, hier volgt mijn probleem, ik heb twéé hele simpele tabelletjes gemaakt, de query zegt alles.

code:
1
2
3
4
5
6
7
8
9
10
11
12
            SELECT
                cat.id,
                cat.name,
                forums.id,
                forums.catid,
                forums.name
            FROM
                cat
            INNER JOIN
                forums
            ON
                ( cat.id = forums.catid )


nu staat er in cat 1 record met id=1 en name=cat1
bij forums staan er 2 records met catid=1 en naam=1.1 en 1.2

Nu zou de output van deze query moeten zijn
cat1 forum1.1
cat2 forum1.2

ik gebruik de volgende php code om te fetchen
PHP:
1
2
3
4
5
$blaat = mysql_query($query);
while ($fetch = mysql_fetch_array ($blaat))
{
    echo $fetch['cat.name'],$fetch['forums.name'];
}


Nu zou ik dunkt me die records toch moeten krijgen.

Niet dat ik een forum oid ga maken maar dit is puur voor test-doeleinden en voor mij nu een onopgelost vraagstuk.

Ik heb zelfs wat gratis forumpakketten gedownload om te kijken hoe hun het doen, zaten er een paar tussen die gewoon while($cat){ while($forum) {}} gebruikte, lijkt me _ERG_ intensief (8>

Hierna ga ik kijken of ik een rechtentabel erbij kan zetten zodat er 3 tabellen met elkaar moeten gaan werken, een tabelletje (we houden het simpel) waar het forumid in staat met wel of niet viewen.

[ Voor 23% gewijzigd door RedHat op 20-02-2005 19:22 ]


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Bij mijn weten kun je geen tabelnamen gebruiken in je gefetchte array. Je query klopt in principe, je PHP code ook, maar je maakt een klein foutje. :P

SQL:
1
2
3
4
5
6
7
8
9
10
11
            SELECT
                cat.id AS cat_id,
                cat.name AS cat_name,
                forums.id AS forum_id,
                forums.name AS forum_name
            FROM
                cat
            INNER JOIN
                forums
            ON
                ( cat.id = forums.catid )

PHP:
1
2
3
4
5
$blaat = mysql_query($query);
while ($fetch = mysql_fetch_array ($blaat))
{
    echo $fetch['cat_name'].$fetch['forum_name'];
}

Dat zou waarschijnlijk meer moeten doen. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • RedHat
  • Registratie: Augustus 2000
  • Laatst online: 18:54
-NMe- schreef op zondag 20 februari 2005 @ 19:36:
een lap php code met een beetje uitleg
Dat zou waarschijnlijk meer moeten doen. :)
Ja dat werkt. Toch wel een voor de hand liggende oplossing, die niet genoemd worden bij de artikels, er zijn dus wel artikels over maar daar kom je niet zo 1-2-3 langs omdat je artikelen opzoekt over inner join natuurlijk.

Nog iets is natuurlijk dat nu bij elk gefetcht forum ook een catid meekrijgt, want je gebruikt een while loop. Dat is iets wat DISTINCT in je query zou moeten oplossen, zodat je geen duplicates krijgt
code:
1
2
3
4
CAT1
FORUM 1.1
CAT1
FORUM 1.2


in plaats van

code:
1
2
3
CAT1
FORUM 1.1
FORUM 1.2


Is een while loop zo-wie-so de enige manier, lijkt me dat er ook andere manieren zijn. Ook met oog op parsetijd.

Het zou ook fijn zijn als het bij iemand opkomt misschien een artikel te plaatsen die dit soort dingen meer "aan het licht" stelt. Ik kan er verrekte weinig over vinden, of gebruik de verkeerde woorden.

[ Voor 40% gewijzigd door RedHat op 20-02-2005 19:54 ]


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

RedHat schreef op zondag 20 februari 2005 @ 19:48:
Nog iets is natuurlijk dat nu bij elk gefetcht forum ook een catid meekrijgt, want je gebruikt een while loop. Dat is iets wat DISTINCT in je query zou moeten oplossen, zodat je geen duplicates krijgt.
Distinct zorgt ervoor dat er geen dubbele records worden afgegeven, en heeft niets te maken met dubbele velden. Je oplossing zal dus niets uithalen, omdat de records verschillen van elkaar. :)
Is een while loop zo-wie-so de enige manier, lijkt me dat er ook andere manieren zijn. Ook met oog op parsetijd.
Er zijn wel andere manieren om je resultset terug te krijgen, maar voor elk van die manieren zul je met een loop door je data heen moeten wandelen. De enige manier om dat echt te optimaliseren, is door een efficiëntere query te gebruiken, wat in dit simpele voorbeeld niet kan. :)
Het zou ook fijn zijn als het bij iemand opkomt misschien een artikel te plaatsen die dit soort dingen meer "aan het licht" stelt. Ik kan er verrekte weinig over vinden, of gebruik de verkeerde woorden.
Ik denk dat je de verkeerde zoekwoorden gebruikt. Sowieso staat de fout die je in je topicstart maakte ook in de documentatie:
If two or more columns of the result have the same field names, the last column will take precedence. To access the other column(s) of the same name, you must use the numeric index of the column or make an alias for the column. For aliased columns, you cannot access the contents with the original column name (by using 'field' in this example).

Example 1. Query with aliased duplicate field names
code:
1
SELECT table1.field AS foo, table2.field AS bar FROM table1, table2

[ Voor 33% gewijzigd door NMe op 20-02-2005 19:58 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • RedHat
  • Registratie: Augustus 2000
  • Laatst online: 18:54
Sorry hier stond een bralverhaal waar niets van klopte.
Krijg op de een of andere manier niet gewoon:
code:
1
2
3
### CAT ###
- forum 1
- forum 2


PHP:
1
2
3
4
while ($fetch = mysql_fetch_array($blaat))
{
    echo $fetch['cat_name'].$fetch['forum_name'] . "<br />";
}


volledig bralverhaal zoals de behulpvolle meneer hieronder ook al vermeld :P _/-\o_

[ Voor 255% gewijzigd door RedHat op 20-02-2005 20:45 ]


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

RedHat schreef op zondag 20 februari 2005 @ 20:12:
Wat zou jij zelf doen, na de query?
While loop, dan krijg je dubbele entry's omdat de catid in het tabel forums 2x voorkomt.
Er zijn denk ik meerdere oplossingen, maar welke is (hoef geen code ofzo dat zoek ik wel lekker zelf uit) technisch gezien de snelste/beste oplossing?
Je zegt het zelf al:
Een while loop en dan de dubbele entry's eruitfilteren met een IFje oid.
:)
De Query valt weinig aan aan te passen, denk dat de query zo moet zijn, de enige manier.
Die query is nog op andere manieren te schrijven, maar functioneel gezien heb je zo de meest optimale.
En als je rechten gaat toekennen, dus we nemen een tabel met userid,forumid,read (om het simpel te houden) dan zou je dus ipv 2 entry's 3 entry's krijgen.
Ik ben bang dat ik die redenatie niet snap. :) Je krijgt straks gewoon records die samengesteld zijn uit 3 tabellen. Daardoor krijg je nog geen dubbele records, tenzij je het ON-gedeelte zou weglaten uit je query, wat volgens mij in deze constructie niet eens mogelijk is. :)
En als de while loop elke keer die 3 tables doorloopt gaat er denk ik heel wat snelheid "verloren".
Je loopt geen drie tables door. Je vraagt éénmalig alle data van die drie tabellen op (die eventueel voldoen aan een bepaald criterium), en die voeg je samen in één resultset. Vervolgens loop je éénmalig door die resultset met alle data uit die drie tabellen heen. En dit alles gebeurt in een fractie van een seconde. :)
RedHat schreef op zondag 20 februari 2005 @ 20:12:
Mijn bericht even weggehaald, beetje onduidelijk.
PHP code die alles _goed_ neerzet: (behalve dat cat's steeds herhaald worden, kan nu ook ff niet zo snel op iets komen dat dat vermijd)
PHP:
1
2
3
4
while ($fetch = mysql_fetch_array($blaat))
{
    if ($fetch['cat_id'] == $fetch['forum_catid']) { echo $fetch['cat_name'].$fetch['forum_name'] . "<br />"; }
}


Maar mijn vraag is dus, of dit anders (sneller) kan, als je 10 cat's hebt, en 40 fora, dan is dit niet echt snel lijkt mij.
Ehm... Right. :P cat_id en forum_catid zijn altijd gelijk, daar heb je nou juist je join op geschreven (tabel1 INNER JOIN tabel2 ON tabel1.veld = tabel2.veld). Die query impliceert dus juist dat die velden altijd gelijk zijn aan elkaar. Die vergelijking is zinloos.
(heb de query ook iets aangepast hoor, maar anders had je geen forum_catid)
forum_catid heb je dan ook niet nodig, omdat die gelijk is aan cat_id. :)

[ Voor 33% gewijzigd door NMe op 20-02-2005 20:43 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • RedHat
  • Registratie: Augustus 2000
  • Laatst online: 18:54
gebruik nu een

PHP:
1
2
3
$catch = "";
while (blablabla)
if $catch != catid echo catid; $catch=catid


werkt :)
Pagina: 1