Přístup do tabulky přes joinovanou tabulku

TMScz
Člen | 24
+
0
-

Ahoj, trochu jsem se zapastil nad jednim dotazem a to tak ze prislo na radu forum:)

Mam 3 tabulky – „products“, „products_variants“, „products_variants_availability“ a pak tabulku s kategoriema, ktera tu nehraje moc roli atd…

Potrebuji udelat select, kde nactu vsechny produkdy dane kategorie a zaroven zjistim skladovou dostupnost jeho variant. Cizi klice jsou nastavene spravne (teda aspon v to doufam) a na dotaz mam nasledujici select (kde se zatim neresi ten soucet na dostupnost ale to neresim).

$rows = $this->db->table('products')
                 ->select('products.*, :products_categories_assoc.*, :products_variants.*, :products_variants_availability.*')
                 ->joinWhere(':products_categories_assoc', 'products.id = :products_categories_assoc.product_id')
                 ->joinWhere(':products_variants', 'products.id = :products_variants.product_id')
                 ->joinWhere(':products_variants_availability', ':products_variants.id = :products_variants_availability.variant_id')
                 ->where(':products_categories_assoc.category_id IN ?', $cids);

Takhle to funguje spravne za predpokladu, kdy tabulka „products_variants_availability“ ma cizi klic primo na produkty, tzn je tam „products.id = products_variants_availability.product_id“. Otazka ale je, proc select nejde, pokud tam ten sloupec a vazba vubec neni? To pak dostavam No reference found for $products->related(products_variants_availability).

Ten 3. join v selectu je prave na tu vazbu varianta > dostupnost, ktery bych cekal ze bude stacit… produkt ma varianty, varianty maji nejakou skladovou dostupnost. takze ta vazba mezi prvni a treti tabulkou mi tam moc nesedi…

Pokud jsem to napsal srozumitelne, tusite nekdo, v cem je kamen urazu? resp. jak by ten dotaz mel byt a jestli to v Nette Database takhle jde vubec napsat?

Dik moc

filsedla
Člen | 82
+
+1
-

Ahoj.

  1. Pokud máš správně nastavené cizí klíče v databázi, podmínky jako 'products.id = :products_categories_assoc.product_id' vůbec nemusíš v kódu uvádět. Nette Database funguje tak, že si je odvodí automaticky. joinWhere() ke specifikování těchto základních joinovacích podmínek neslouží, ani kdybys je v databázi specifikované neměl, viz např. odpověď v tomto vlákně. Tj. joinWhere() nepoužívej, ledaže bys chtěl specifikovat další podmínky v JOIN … ON … AND …
  2. Z hlediska zápisu ve stylu Nette Database, tam máš chybu. Proto to nefunguje. Když napíšeš ':products_variants_availability' v dotazu začínajícím ->table('products'), znamená to v podstatě 'products:products_variants_availability', tj. Nette Databázi tím říkáš, že chceš použít relaci mezi productsa products_variants_availability. Jenže ta neexistuje.

    Pokud to není přímá relace, musíš zapsat „celou cestu“, tj. ':products_variants:products_variants_availability'.

Editoval filsedla (17. 7. 2019 11:47)

filsedla
Člen | 82
+
+2
-

A navíc, nemusíš vůbec ani používat select(). Ten je také automatický. Pokud tomu přizpůsobíš další kód, Nette Database selectuje pouze ty sloupce, které opravdu využiješ.

TMScz
Člen | 24
+
0
-

Tak to funguje jeste lip nez jsem si celou dobu myslel… a (ne)pouziti joinWhere vysvetluje, proc jsem tam mel pak tu podminku dvakrat :)

Dik moc, tohle pomohlo, zase o trochu chytrejsi :)