ugrás a tartalomhoz

FLWOR MySQLben

vbence · 2006. Aug. 24. (Cs), 11.07
Halihó!

Ugyebár a relációs adatbázisok eredmánytáblát adnak vissza. Nem úgy, mint a FLWOR, az SQL képtelen hierarchiát (pontosabban az ehhez szükséges különböző egyedeket) egy eredménytáblában visszaadni. Érdekelne ki hogyan valósítja meg a hierarchikus logikát a lekérdezésekben. Itt van egykét megoldás amire gondolok, de mindegyiknek van valami kisebbnagyobb hibája.

A két tábla legyen "cikk" és "rovat". A "$where" pedig tételezzük fel, hogy valami közepesen bonyolult szűrő.


Egyesített query
Előny: egyetlen SQL lekérdezést kell csak értelmezni, végrehajtani, a MySQLnek.
Hátrány: nagy adatforgalom az adatbázis és a php között. Ha külön szerveren van az adatbázis, akkor még problémásabb.

$db->query("SELECT rovat.id AS rid, rovat.cim AS rcim, cikk.id AS cid, cikk.cim AS cid FROM cikk LEFT JOIN rovat ON rovat.id=cikk.rovat WHERE $where");
$utolsorovat = 0;
while ($rec = $db->fetch ()) {
    if ($rec["rid"] != $utolsorovat) {
        echo ('<div class="rovat">' . $rec["rcim"] . '</div>');
        $utolsorovat = $rec["rid"];
    }
    echo ('<div class="cikk">' . $rec["ccim"] . '</div>');
}
Párhuzamos queryk
Előny: nincs fölösleges adatforgalom, minden csak egyszer szerepel az eredményben.
Hátrány: Gyakorlatilag ugyanaz a query fut le kétszer. Nem tudom a MySQL mennyire tudja optimalizálni őket, kihasználja-e, hogy a WHERE igazsághalmaza ugyanaz a két lekérdezésben.

$db->query("SELECT rovat.id AS rid, rovat.cim AS rcim FROM cikk LEFT JOIN rovat ON rovat.id=cikk.rovat WHERE $where GROUP BY rovat.id");
$db2->query("SELECT rovat.id AS rid, cikk.id AS cid, cikk.cim AS ccim FROM cikk LEFT JOIN rovat ON rovat.id=cikk.rovat WHERE $where");
$utolsorovat = 0;
while ($rec = $db->fetch ()) {
    if ($rec["rid"] != $utolsorovat) {
        $rec2 = $db2->fetch ();
        echo ('<div class="rovat">' . $rec2["rcim"] . '</div>');
        $utolsorovat = $rec["rid"];
    }
    echo ('<div class="cikk">' . $rec["ccim"] . '</div>');
}
Beágyazott SQL
Biztos lehet így is, de én nem igazán használok ilyet a gyakorlatban, úgyhogy ha valakinek van kedve írhat rá példát. Lehet, hogy pont ez lenne a jó megoldás amit keresek.
 
1

SQL is tud hierarchiát

Hodicska Gergely · 2006. Aug. 24. (Cs), 14.05
Szia!


A FLOWR-t nem ismerem még, viszont az SQL is képes akár natívan is kezelni hierarchiát. Pl. Oracle esetén ott a connect by utasítás. Postgresql esetén is van egy connectby contrib csomag, illetve egy ugyanilyen célú, Oracle féle szintaktikát biztosító patch is.

Ezenkívül van még többféle módszer is arra, hogy úgy tárolj fát adatbázisban, hogy egy lekérdezéssel ki tudd szedni a teljes (rész)fát a DB-ből. Pl. lásd Poetro cikkét, ami az adjacency list model nevű megoldást mutatja be. De létezik pl. path enumeration néven futó megoldás is, meg még egyéb lehetőségek is vannak.


Felhő
2

Ennél egyszerübb

vbence · 2006. Aug. 24. (Cs), 17.16
Olvastam a cikket, de ott picit más feladatra keresik a megoldást, és főleg ugyanolyan egyedek között. Az én problémám sokkal hétköznapibb, egy egyszerű külső kulcsos egy-a-sokhoz kapcsolatot szeretnék listázni, mint egy tartalomjegyzék. A mélység csupán egy, vannak címek és vannak elemek (a címek alatt). Jó példa a következő oldal:
http://www.fotexnet.hu/sid000000/page/category/039 (férfi cipők, gyermek cipők stb).

A kérdés csak annyi, hogyan lehet ezt elegánsan vagy a lehető legkevásbé bután csinálni.
3

Még 1 módszer

vbence · 2006. Aug. 24. (Cs), 17.23
Itt van még egy megoldás a témára, szintén kis szépséghibával.

Másodlagos (id alapú) queryk
Előny: a $where szűrőit csak egyszer kell alkalmazni
Hátrány: Sok query fut le, minden szülőhöz (rovat) egy-egy önálló query-t kell értelmezzen az adatbázis.
$db->query("SELECT cikk.rovat AS rid, cikk.id AS cid, cikk.cim AS ccim FROM cikk WHERE $where");
$utolsorovat = 0;
while ($rec = $db->fetch ()) {
    if ($rec["rid"] != $utolsorovat) {
        $db2->query("SELECT rovat.id AS rid, rovat.cim AS rcim FROM rovat WHERE id=' . $rec["rid"] . '");
        $rec2 = $db2->fetch ();
        echo ('<div class="rovat">' . $rec2["rcim"] . '</div>');
        $utolsorovat = $rec["rid"];
    }
    echo ('<div class="cikk">' . $rec["ccim"] . '</div>');
}
4

esetleg group_concat

Hodicska Gergely · 2006. Aug. 24. (Cs), 18.00
Körülményektől függően érdemes lehet elgondolkodni a mysql group_concat függvényének bevetésén. Joinolod a rovat és cikk táblákat, szűrsz, rovat id szerint group by, majd az cikk id és cím mezőket egy-egy group_concat függvényen keresztül kéred el. Arra kell csak vigyázni, hogy az elválasztó karakter(sorozat) ne szerepelhessen a címben.


Felhő
5

kiróbálom...

vbence · 2006. Aug. 25. (P), 23.17
Köszi. Sajnos nincs ötös mysql a közelben, de valahol majd kipróbálom a dolgot.

Furcsálom, hogy egy ilyen (szerintem legalábbis) hétköznepi feladatra nincs bejáratott megoldás... :o
6

régebbi verziókban is van

Hodicska Gergely · 2006. Aug. 26. (Szo), 13.56
Felhő