ugrás a tartalomhoz

mysql_query "hierarchikus" lekérdezés

eBandee · 2011. Feb. 1. (K), 01.47
Üdv!

A cím, lehet hogy nem pontos, de egy érdekes problémába ütköztem. A probléma lényege az lenne, hogy adott 2 adattábla, amit egy segédtáblával szeretnék összekötni. A segédtáblában, csak az első és a másik táblában tárolt sorok ID-je található. Röviden egy sorhoz több sort rendelnék a másik táblából.

Az első táblában mondjuk, foci csapatok vannak, a másodikban, pedig játékosok, a segédtábla pedig tartalmazza, hogy melyik csapathoz melyik játékosok tartoznak. (ez csak egy példa)

Szeretném megoldani, hogy egy mysql_query lekérdezéssel lekérem a csapatokat, és a csapatokhoz tartozó tartozó játékosokat.

Egyféle megoldást ismerek, ami a következő:

$csapatok = mysql_query( "SELECT * FROM csapatok" );
while( $csapat = mysql_fetch_object( $csapatok ) ){

  echo $csapat->csapatNeve."<br/>";
  
  $jatekosok = mysql_query( 
       "SELECT * FROM segedtabla,jatekosok 
        WHERE segedtabla.csapatID = $csapat->csapatID 
        AND segedtabla.jatekosID = jatekosok.jatekosID" 
  );
  
  while( $jatekos = mysql_fetch_object( $jatekosok ) ){
    echo "--".$jatekos->jatekosNeve."<br/>";
  }

}
Ez eddig szép és jó, de ha egy lekérdezésben kérném le, akár JOIN-nal, vagy ahogy az előbbi példában, akkor a csapat adatait annyiszor kéri le, ahány játékos van. A kérdésem pedig az lenne, hogy ilyesfajta problémákat meg lehet-e úgy oldani, hogy mondjuk egy GROUP BY - al csapatID szerint csoportosítom, de a csapathoz tartozó játékosok a csapat "alá rendelve" megmaradjanak? ( mondjuk egy több dimenziós tömbben )

Mondjuk ez elég hülye példa, de vannak bizonyos esetek, ahol jól jönne erre valami elegánsabb megoldás.

A válaszokat előre is köszi!
 
1

Szerintem így nem

bb0072 · 2011. Feb. 1. (K), 11.40
Hát ha erre van valamilyen megoldás, az engem is érdekelne, de alapból a szabály az, hogy egy lekérdezés egy táblázat formában értelmezhető kimenetet ad. Ez lehet akár egy darab érték vagy skalár (1x1 méretű táblázat), illetve bármekkora 2 dimenziós tábla.

Én ezt egy queryvel, LEFT JOIN-nal csinálnám meg (GROUP BY nélkül), és a while ciklusban figyelnék rá, hogy még ugyanabban a csapatban vagyunk-e, vagy már a következő jön.
2

plusz order by

bb0072 · 2011. Feb. 1. (K), 11.50
Ja igen, és ORDER BY csapatid szerint, hogy együtt legyenek a csapatok. Másodlagos order lehet játékos névsorrend vagy pozíció szerint, pl kapusok előre, aztán hátvédek stb.
3

A lekéréssel nincs baj végülis...

eBandee · 2011. Feb. 1. (K), 16.13
...de ezt php-ben hogy jelenítem meg? Mert ha jol tudom, a MySQL engedélyezi az ilyesfajta lekérdezést, hogy egy sorhoz több sort kapcsolunk, de pl ez mysql_fetch_object-tel, sem mysql_fetch_array-el nem működik. Hiába jó a lekérdezés, ezek a függvények csak az egy az egyhez lekérdezéseket támogatják, ami annyit jelent, hogy az alárendelt sorokból ( a példában a játékosokból ) csak egyet lát a függvény.

A fenti megoldás viszont egy nagyobb terhelésnél marha lassú lehet... Főleg ha mondjuk egy több szintű, 1 a többhöz lekérdezést végzünk, jó sok elemmel, pl egy többszintű dropdown menü előállításához, amit minden oldalon ki kell rajzolni.

Mert ahogy tapasztaltam, ha sok a mysql_query hívás, nagyon lelassíthatja az oldalt... Sokkal jobban, mintha csak 1 mysql_query lenne, és utána a lekért adatokkal operálnánk.

Szerk1.: Azthiszem pontosítva a dolgot, egy 1:n - hez szerkezetből kellene lekérni az adatokat, egy lekérdezéssel.
5

Valamit félreértesz. A

bb0072 · 2011. Feb. 2. (Sze), 13.20
Valamit félreértesz. A lekérdezés így nézne ki:

SELECT cs.csapatID, cs.csapatNeve, j.jatekosID, j.jatekosNeve
FROM csapat cs
LEFT JOIN segedtabla s ON(cs.csapatID = s.csapatID)
LEFT JOIN jatekosok j ON (j.jatekosID = s.jatekosID)
ORDER BY cs.csapatID ASC, j.jatekosNeve ASC;
Ezt tudod fetchelni. Hajtsd végre ezt a queryt konzolon vagy phpmyadminban, és nézd meg az eredményt!
6

Egyébként nem is 1:n a

bb0072 · 2011. Feb. 2. (Sze), 13.40
Egyébként nem is 1:n a kapcsolat, hanem n:m, tekintve hogy egy játékos tagja lehet a klubcsapatának és pl. a válogatottnak is. Nem tudom, hogy az alkalmazásod kezel-e ilyesmit, de ez a query amit írtam, ezzel is elbír.

Ha viszont tényleg 1:n a kapcsolat (pl egy adott nemzeti bajnokság csapatai és az ott szereplő játékosok), akkor itt adatbázisszervezési gondok vannak, mert ez esetben a segedtabla-ra nincs is szükséged. A jatekosok táblában tartsd nyilván a játékoshoz tartozó csapatot ID szerint. Így csak két táblát join-olsz, és a lekérdezés is gyorsabb. A segédtábla pont az n:m kapcsolatok leírására szolgál.

Ja és ne feldkezz meg az indexelésről. A csapatok.csapatID és a jatekosok.jatekosID elsődleges kulcs, és az order by miatt a jatekosok.jatekosNeve -re is tegyél egy indexet. Így még gyorsabb lesz a query.
4

join

Török Gábor · 2011. Feb. 1. (K), 18.13
Ez eddig szép és jó, de ha egy lekérdezésben kérném le, akár JOIN-nal, vagy ahogy az előbbi példában, akkor a csapat adatait annyiszor kéri le, ahány játékos van.
Ez miért baj? Nyerd ki egy lekérdezéssel az adatokat, és utána PHP-val alakítsd számodra megfelelő struktúrára.
7

Igaz is...

eBandee · 2011. Feb. 2. (Sze), 15.55
Csak már azon agyaltam, ezt hogy lehetne még optimálisabbá tenni, bár ha belegondolok, sokkal jobb teljesítményt amúgy sem érnék el vele, még ha meg is lehetne valósítani...

Amúgy adatbázis szervezési gondok lehetnek, mert ezt a példát csak a bejegyzés írása közben találtam ki. Egy általános megoldásra voltam kíváncsi 1:n és n:m szerkezet lekérésére, amit meg is kaptam, szóval köszi!