Nette\Database Join dvou tabulek

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

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
+
+1
-

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
+
0
-

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)

vvoody
Člen | 910
+
0
-

Ďalších x dotazov? Máš to otestované? Koľko ti ich zobrazí debug bar ak použiješ ref/related?

tomas.lang
Člen | 53
+
+1
-

Ahoj, záleží jestli chceš dělat dotazy 1:n, nebo m:n.

  1. ř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.

  1. ř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 a tag) (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
+
0
-

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)

Grelek
Člen | 233
+
0
-

Dokumentace se dost řeší. Aktuálně se s tím oproti předchozím měsícům hodně hýbe k lepšímu.

Editoval Grelek (8. 7. 2013 9:15)

Majko
Člen | 11
+
0
-

Grelek napsal(a):

Dokumentace se dost řeší. Aktuálně se s tím oproti předchozím měsícům hodně hýbe k lepšímu.

Tak to rád slyším :) Díky! ^^