Boj s vazbami M:N + cizi klice

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Duch.Veliky
Člen | 68
+
0
-

Zdravím,

válčím trošku s tím jak správně používat dotazy používající vazby M:N. Už jsem konečně zprovoznil funkčí dotaz, akorát že mi to místo jednoho dotazu dělá 3 dotazy a to není úplně to, co by mělo.

TABULKA 1:
uzivatele_shopy
shop (int)
uzivatel (int)

  • dva cizí klíče:
  • shop (uzivatele_shopy.id na shopy.id)
  • uzivatel (uzivatele_shopy.uzivatel na uzivatele.id)

TABULKA 2:
shopy
id (int)
nazev (varchar)

TABULKA 3
uzivatele
id (int)
jmeno (varchar)

Testovací dotaz mám:

<?php
$shopy = $this->database->table("uzivatele_shopy")
                        ->where("uzivatel", $this->user->getId());

            foreach ($shopy as $shop) {
                echo $shop->ref("shop")->nazev;
            }
?>

A místo aby to načetlo jenom jeden dotaz, tak to dělá:
1)
SELECT shop, shopy
FROM uzivatele_shopy
WHERE (uzivatel = 1)

2)
SELECT *
FROM uzivatele_shopy
WHERE (uzivatel = 1)

3)
SELECT id, nazev
FROM shopy
WHERE (id IN (1))

Jako výsledek mi to vrátí, ale trochu divným způsobem :)

Editoval Duch.Veliky (10. 9. 2014 19:19)

Mysteria
Člen | 797
+
+1
-

Ano, NDBT takhle funguje, místo jednoho JOIN dotazu udělá víc menších, který jsou efektivnější.
Co se týká samotných dotazů, tak generovat by to mělo pouze dva – při prvním spuštění 2 a 3 (protože neví, jaký sloupce budeš chtít tak *) a při dalších 1 (protože už ví, jaký přesně data potřebuješ) a 3.

Editoval Mysteria (10. 9. 2014 19:23)

David Matějka
Moderator | 6445
+
+1
-

Jestli chces vybrat vsechny shopy, co ma uzivatel, muzes pouzit tzv. „backjoin“, viz doc

wodCZ
Člen | 49
+
0
-

Snad se nepletu, ale psal bych to takto:

$vazby = $this->database->table("uzivatele_shopy")
                        ->where("uzivatel", $this->user->getId());

            foreach ($vazby as $vazba) {
                echo $vazba->shopy->nazev;
            }
Duch.Veliky
Člen | 68
+
0
-

Díky, kouknu i na ten backjoin.

@Inkode to jsem zkoušel původně taky, ale vracelo to
Nette\MemberAccessException
Cannot read an undeclared column ‚shopy‘.

A když jsem tam dal jenom $shop->shop->nazev, tak zase
Notice
Trying to get property of non-object

Funguje jenom ten tvar s tim ref() a ještě nevím proč, to teď zkoumám :)

David Matějka
Moderator | 6445
+
0
-

@Duch.Veliky kdybys mel ten sloupecek ve spojovaci tabulce pojmenovany shop_id, fungovalo by i treba $vazba->shop->nazev – pokud se totiz nenajde sloupecek (shop) zkusi se NDBT kouknout, jestli neexistuje sloupecek s FK, ktery tento retezec obsahuje (shop_id).

Pri soucasne strukture by ti tak melo fungovat treba $vazba->sho->nazev ale to radeji ten ref :)

Editoval matej21 (10. 9. 2014 19:34)

Duch.Veliky
Člen | 68
+
0
-

@matej21 jo máš pravdu, když tam dám „sho“, tak to funguje. Tak aspoň vím, jak to mám do budoucna pojmenovávat. Díky