počet záznamů v nad.nadřízené tabulce (ob jednu) – 2× join

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

Zdravím,
mám takovou divokost:

create table okres (
  id integer,
  nazev varchar);
create table obec (
  id integer,
  nazev varchar,
  okres_id integer references okres);
create table lv (
  id integer,
  obec_id integer references obec)

jak by měla vypadat konstrukce, která vytáhne tabulku okresů a počtu lv v ní obsažených – cosi na způsob:

select okres.id, okres.nazev, count(*) as pocet from lv join obec on lv.obec_id = obec.id join okres on okres.id=obec.okres_id group by okres.id, okres.nazev;

Přiznávám, že je to šílenost :), ale hodilo by se mi … Zkusil jsem:

<?php
$this->connection->table('lv')->select('okres_id, okres.nazev, COUNT(*) AS pocet')->group('okres.id, okres.nazev, obec.okres_id,lv.obec_id');
?>

ale to se mu nelíbí: No reference found for $okres->pocet. Mě také ne. Ale nevím, jak na to.

petr.pavel
Člen | 535
+
0
-

Ve tvém příkladu nevidím přiřazení proměnné $okres. Máš to takhle?

<?php
$okres = $this->connection->table('lv')->...
?>

Problém možná bude v tom, že nesestavuješ dotaz do NDB správně a tudíž výsledek není řádka, ale null/false (už si nevzpomínám, co vrací NDB po chybě).

Taky musíš NDB vysvětlit, jak má navázat okres na obec – takhle se (předpokládám) snaží získat okres rovnou přes lv. Zkus lv.obec.okres.id a lv.obec.okres.nazev.

V debug panelu si můžeš zkontrolovat, jestli je výsledný dotaz takový, jaký si představuješ. A taky, kolik řádek vrátil. Výborná věc.

Ještě na okraj, v GROUP BY máš zbytečně moc věcí – aspoň v porovnání s dotazem, který jsi psal, že chceš vyrobit.

P.S. Zalamuj, prosím, v ukázkových zdrojácích řádky, ať nemusím posouvat sem a tam.

vvoody
Člen | 910
+
0
-

@jik: bude potrebne na zaklade dat z joinovanych tabuliek filtrovat/zoradovat? Co takto skusit nette like sposob bez joinov?

jik
Člen | 146
+
0
-

Omlouvám se za zápis, to jsem opravdu napsal blbě. Tedy sql trochu lépe:

select okres.id, okres.nazev, count(*) as pocet from lv
join obec on lv.obec_id = obec.id join okres on okres.id=obec.okres_id
group by okres.id, okres.nazev;

Spáchal jsem to do modelu takto:

<?php
public function getOkrSum ($id) {
	return $this->connection->table('lv')
		->select('okres_id, okres.nazev, COUNT(*) AS pocet')
		->group('okres.id, okres.nazev, obec.okres_id,lv.obec_id');
}
?>

To, že nette zobrazuje sql dotazy je vynikající a samozřejmě toho využívám. Vím, že ten dotaz do NDB je vadný, ale prostě nevím, jak ho sestavit správně. Nechci totiž seskupovat podle obcí, ale výhradně jen podle okresů. Zatím mi funguje počítání do 1. nadřazené tabulky:

<?php
public function getObokrSum ($id) {
	return $this->connection->table('lv')
		->select('obec_id, obec.nazev, COUNT(*) AS pocet')
		->group('obec.id, obec.nazev, lv.obec_id')->where('okres_id',$id);
}
?>

Část group v tom dvoupatrovém dotazu je jasně špatně, ale vlastně nevím, jak navázat tabulku okres přes tabulku obec na tabulku lv.
Snad by šlo použít where ve tvaru WHERE okres.id=obec.okres_id AND obec.id=lv.obec_id ale jak toto vlastně zapsat? Zatím jsem našel pouze případ kdy:

WHERE tab.sloupec=hodnota

např.

...->where(tab.sloupec= ?, hodnota)...
...->where(tab.sloupec=>hodnota)...

ale já potřebuji:

WHERE tab1.sloupec1=tab2.sloupec2

Pokud jsem napsal něco na způsob

...->where(tab1.sloupec1=tab2.sloupec2)

tak mi to vynadalo, že motám text do integeru.

vvoody: snažím se celou záležitost zjednodušit, konkrétně viz to $id v hlavičce funkce – ano, až zvládnu to počítání záznamů ob tabulku, přijde ještě where a potom order.

Už mě taky napadlo, že by se některé ptákoviny daly šikovně řešit dvojicí dotazů, které by naplnily 2 proměnné (pole), kterými by se potom současně vyplňovala šablona. Tedy první proměnná by procházela cyklem foreach a druhou … nejde v těch polích v šabloně nějak vyhledávat? Tedy něco na způsob:

{foreach $okresy as $okres}
	{$obce[okres_id={$okres->id}]->bunka}
{/foreach}
vvoody
Člen | 910
+
0
-

Tak inak. Ako chces aby vyzeral vystup, cize sablona? Bude sa iterovat najskorej cez okresy a potom obce? (npr ak chces mat oddelene obce podla okresov)

{foreach $okresy as $okres}
	{foreach $okres->obce as $obec}

	{/foreach}
{/foreach}

alebo chces iterovat priamo nad vsetkymi obcami?

{foreach $obce as $obec}

{/foreach}

Vytvor si proste sablonu a neries pri tom kde ziskat data (pouzi nazvy premennych a ich properties aby z toho bolo jasne ktore data z db to budu, npr ako som napisal $okres->obce) potom to pastni sem a podla toho uz budeme vediet zvolit efektivne riesenie pre tvoj projekt a nie snazit sa zostavit join ktory mozno ani nepotrebujes.

jik
Člen | 146
+
0
-

Problém vypadá takto: mám kraje, okresy a obce, což je vlastně neměnná záležitost. Potom mám tabulku subjektů, kteří vlastní položky v tabulce lv. Různé subjekty mohou mít lv v různých obcích. A proto potřebuji, aby se každému subjektu zobrazovaly pouze ty kraje (a v nich okresy a dále obce), ve kterých má záznamy na lv.
Poznámka: děkuji za nakopnutí, teď jsem si uvědomil, že ten count(*) vlastně nepotřebuji.

Mělo by to jít, toto je vlastně podobné, tady se o tom také píše – ve tvaru („$table1.$table2.$column“). Ale jak to vlastně zapsat?

Editoval jik (5. 8. 2012 22:53)

jik
Člen | 146
+
0
-

Tak hlavní problém byl vyřešen smazáním cache …

petr.pavel
Člen | 535
+
0
-

@jik: Souhlasím s @vvoody. Odpověz mu, prosím, na otázku. Je častým hříchem lidí, kteří začínají s NDB/NotORM, že uvažují postaru, dotazy si skládají sami a snaží se na to napáčit NDB/NotORM. Správné je začít uvažovat tak, jak popsal @vvoody.