Nette\Database Join dvou tabulek
- Majko
- Člen | 11
Zdravím,
začínám mít na Nette\Database (potažmo na její dokumentaci) slušnou zlost a začíná mě to dohánět k zoufalství a šílenství.
Nejsem schopen dohledat jak udělám primitivní hloupý join dvou tabulek. Googlím, hledám tady na fóru, zkouším, v dokumentaci je (s prominutím) úplný hovno a nikde zkrátka není ucelená informace o tom, jak joinuju tabulky a tahám z nich data.
Co vím a nefunguje mi:
- Vím, že primární klíč se musí jmenovat id, a sloupec s cizím klíčem v druhé tabulce, který chci spojit se musí jmenovat tabulka_id
- Vím, že můžu použít ->ref() nebo ->related(), ale to jsou zbytečné dotazy navíc, to nechci. Chci join.
Možná mám strukturu tabulky blbě, nebo jsem to blbě napsal do šablony. Vůbec nemám tucha. S Nette\Database navíc nedělám moc dlouho, takže třeba jsem jen blbec já.
Prostě chci spojit tabulky products a product_images tak, abych pak mohl v šabloně pracovat s url_default.
Pokud to nejde, řekněte mi to rovnou, hodím tam ->query() a nebudu se s tím dál zabývat. Jen by mě potom zajímalo, proč tak nedodělané Nette\Database nezůstalo někde v betaverzi a šlo to rovnou to releasu?
Mockrát díky všem za odpovědi a rady :)
- craz
- Člen | 34
Podla mna by to malo fungovat s pouzitim related takto:
{foreach $featuredproducts as $product}
<article>
{foreach $product->related("product_images") as $product_images}
<div class="prod-image" style="background-image: url('{$basePath}{$product_images->url_default}')"><a n:href="Product:show $product->id"></a></div>
{/foreach}
<a n:href="Product:show $product->id"><h3>{$product->name}</h3></a>
<div class="short">{$product->description|truncate:60}</div>
<div class="price"><a n:href="Product:show $product->id">{if $product->sale}<span class="sale label label-info">-{$product->sale_perc*100}%</span>{/if}</a><a n:href="Product:show $product->id">{$product->price},- Kč</a></div>
</article>
{/foreach}
Editoval craz (7. 7. 2013 12:07)
- Majko
- Člen | 11
craz napsal(a):
Podla mna by to malo fungovat s pouzitim related takto:
Díky za bleskovou odpověď, ale psal jsem, že se ptám konkrétně na join, dávat do toho další foreach s related nechci, protože to je dalších x dotazů a je to pak zbytečně náročnější.
Editoval Majko (7. 7. 2013 12:18)
- tomas.lang
- Člen | 53
Ahoj, záleží jestli chceš dělat dotazy 1:n, nebo m:n.
- řekněme, že mám knihu a chci získat jméno jejího autora (1:n), pak by to mohlo vypadat nějak takto:
<?php
$database->table('book')->select('author.name author_name');
?>
Položený dotaz:
SELECT `author`.`name` `author_name`
FROM `book`
LEFT JOIN `author` ON `book`.`author_id` = `author`.`id`
Použití přepokládá že existuje cizí klíč na tabulce
book
který ji navazuje záznam z author
. Tento postup
by se dal samozřejmě ještě více zanořovat.
- řekněme, že chci získat všechny knihy které mají alespoň jeden tag a
zároveň počet jejich tagů (tabulky jsou
book
,book_tag
atag
) (m:n):
<?php
$database->table('book')
->select('book.id, COUNT(book_tag:id) tag_count')
->group('book.id', 'tag_count > 0');
?>
Položený dotaz:
SELECT `book`.`id`, COUNT(`book_tag`.`id`) `tag_count`
FROM `book`
LEFT JOIN `book_tag` ON `book`.`id` = `book_tag`.`book_id`
GROUP BY `book`.`id`
HAVING `tag_count` > 0
Použití přepokládá Nette ve verzi 2.0.x, ve verzi 2.1dev by to pak
myslím vypadalo
$database->table('book')->select('book.id, COUNT(:book_tag.id) tag_count')
…
No a teď si představme, že chcem vytáhnout všechny knihy které mají
tag
např. slova „good book“:
<?php
$database->table('book')
->where('book_tag:tag.title', 'good book')
->group('book.id');
?>
Položený dotaz:
SELECT `book`.`id`
FROM `book`
INNER JOIN `book_tag` ON `book`.`id` = `book_tag`.`book_id`
INNER JOIN `tag` ON `book_tag`.`tag_id` = `tag`.`id`
WHERE (`tag`.`title` = 'good book')
GROUP BY `book`.`id`
Tak toto byl takový průstřel letem světem, asi kdyby jsi chtěl zjistit více, doporučuji kouknout na záznam tohoto videa: http://www.youtube.com/watch?… a nebo alespoň na slidy k němu: http://public.skrasek.com/…_2012_04_28/#1.
Editoval tomas.lang (7. 7. 2013 14:19)
- Majko
- Člen | 11
Díky chlapi za vysvětlenou.
tomas.lang obzvláště – vyčerpávající odpověď a díky za užitečné linky.
vvoody napsal(a):
Ďalších x dotazov? Máš to otestované? Koľko ti ich zobrazí debug bar ak použiješ ref/related?
Ač to nemuselo být napsáno tak trochu útočně, díky, netušil jsem, že i když použiju foreach, tak Nette místo dvaceti dotazů udělá jen dva. To by se dalo použít a očividně to i funguje.
Je vážně škoda, že taková podrobnější dokumentace není dodělána. Možná by někdo z vás ji mohl pro nováčky dodělat a udělat tak dobrý skutek :)
Editoval Majko (8. 7. 2013 9:08)