Použití „related“ přes více 1:N relací

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

Ahoj. Snažím se přijít na to, jestli se skrz „related“ dá nějak chytře sáhnout až do tabulky „ob“ jednu relaci. Typickým příkladem může být vazba tabulek ve stylu „Univerzity > Fakulty > Studenti“, kdy obě vazby jsou 1:N. (každá univerzita má více fakult, každá fakulta má více studentů).

No a mě by zajímalo, jestli se dají nějak chytře vypsat všechny univerzity a ke každé všichni její studenti. Určitě by to šlo udělat trojitým foreach cyklem, ale mě zajímá, jestli by se nějak nedaly „přeskočit“ fakulty. Představuju si, že by to mohlo fungovat nějak takto:

<?php

{foreach $universities as $university}
	{$university->name}
	{foreach $university->related('faculty','universityId')->related('student','facultyId') as $student}
		{$student->name}
	{/foreach}
{/foreach}

?>
romiix.org
Člen | 343
+
0
-

Asi to nepôjde, keďže related() sa volá na ActiveRow, ale vracia GrupedSelection, ktoré related() nemá. Možno by nebolo odveci implementovať to.

Pavel Kravčík
Člen | 1205
+
0
-

Pokud se těch závislostí nabalí příliš – zabiješ výkonnost.

Napadá mne:

  1. Studenti budou mít universityId (snadné volání všech studentů bez nutnosti šahat do tabulky fakulty).
  2. Napsat si na to přímo dotaz v SQL (tak to většinou řeším přes left joiny a nastavování aliasů, selectů a indexů → mnohonásobně vyšší výkonnost při velkých tabulkách).
koren
Člen | 59
+
0
-

Pavel Kravčík napsal(a):

Pokud se těch závislostí nabalí příliš – zabiješ výkonnost.

Napadá mne:

  1. Studenti budou mít universityId (snadné volání všech studentů bez nutnosti šahat do tabulky fakulty).
  2. Napsat si na to přímo dotaz v SQL (tak to většinou řeším přes left joiny a nastavování aliasů, selectů a indexů → mnohonásobně vyšší výkonnost při velkých tabulkách).

Ta výkonnost asi žádné terno nebude no :)

Varianta 1) mě napadla, ale nelíbí se mi na tom ten fakt, že pak by v databázi duplikovaly některé informace. Nakonec teda zřejmě sáhnu po 2).

Možná mě tedy spíš zajímá, jestli už náhodou není v Nette\Database nějaká zjenodušená funkce pro joinování (bez nutnosti psát vlastní SQL dotaz).

A ještě jedna otázka. Tu výkonnost zabíjí už samotný fakt, že jsou ty tabulky provázané, nebo až přílišné používání related()?

Editoval koren (12. 10. 2015 18:49)

David Matějka
Moderator | 6445
+
+2
-

Možná mě tedy spíš zajímá, jestli už náhodou není v Nette\Database nějaká zjenodušená funkce pro joinování (bez nutnosti psát vlastní SQL dotaz).

->table('student')->where('faculty.universityId', $id);

viz doc https://doc.nette.org/…ase/explorer#…

Pavel Kravčík
Člen | 1205
+
0
-

koren napsal(a):

A ještě jedna otázka. Tu výkonnost zabíjí už samotný fakt, že jsou ty tabulky provázané, nebo až přílišné používání related()?

Nejsem žádný expert, ale jeden dotaz (i když velký) se provede rychleji než 30.000 dotazů i když jednoduchých (lock, query, commit). Nejsem si jistý, ale občas mi přijde že vypadne správné „selectování“, tj. se tahá celá tabulky místo 1 sloupce, který je pak potřeba. Když si nastavíš SELECT id,name máš jistotu, že to bude rychlejší. Ale třeba plácám nesmysly, hlouběji jsem to neřešil a na větší věci opustil cykly s related().