Nette\Database výpis kategorie s počtem záznamů
- motorcb
- Člen | 552
Zdravím.
Opět jsem pokročil s Nette – je to super framework :-)
Nyní řeším následující problém – dotaz. Mám bazar ve kterém bych
chtěl vypsat sekce a počet inzerátů v dané sekci.
DB:
CREATE TABLE IF NOT EXISTS `bazar` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`bazar_category_id` int(11) DEFAULT NULL,
`date` datetime DEFAULT NULL,
`title` varchar(100) COLLATE utf8_czech_ci DEFAULT NULL,
`text` mediumtext COLLATE utf8_czech_ci,
KEY `id` (`id`,`user_id`,`bazar_category_id`),
KEY `bazar_category_id` (`bazar_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci AUTO_INCREMENT=149 ;
CREATE TABLE IF NOT EXISTS `bazar_category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) COLLATE utf8_czech_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci AUTO_INCREMENT=21 ;
ALTER TABLE `bazar`
ADD CONSTRAINT `bazar_ibfk_3` FOREIGN KEY (`bazar_category_id`) REFERENCES `bazar_category` (`id`),
Chtěl bych vypsat kategorie (tabulka bazar_category) a k nim počet inzerátů v dané kategorii (tabulka bazar )
Ale v praxi dokáži vypsat jen kategoriie:
$this->context->createBazar_category();
Nevěděl by prosím někdo jak v Nette\Database udělat dotaz, který by
navíc ještě dokázal spočítat počet záznamů s daným bazar_category_id
v tabulce bazar
?
Děkuji za jakékoliv nakopnutí a přeji hezký zbytek dne
- jtousek
- Člen | 951
Jestli jsem někde neudělal chybu tak potřebuješ tenhle dotaz:
SELECT name, COUNT(bazar.id) AS count
FROM bazar_category JOIN bazar ON bazar_category_id = bazar_category.id
GROUP BY bazar_category_id
Bohužel mi uniklo jak donutit Nette\Database udělat JOIN, snad poradí někdo další.
- Caine
- Člen | 216
V nette\database se join vytváří automaticky, stačí psát jen jaký tabulky se v dotazu použijou (např. bazar.id, resp bazar:id) a v závislosti na použitý reflexi, se sami doplněj joiny. Pro takovej dotaz by mělo stačit následující.
$selection = $connection->table('bazar_category')->select('name')->select('COUNT(bazar:id) AS count')->group('bazar_category_id');
//dvojtecka u bazar:id je backjoin, bazar odkazuje na kategorii,
//pokud by tam byla tecka, snazilo by se to udelat join s tim,
//ze kategorie odkazuje na bazar (coz je blbost).
foreach ($selection as $row) {
echo $row->name . ': ' . $row->count;
}
//nebo
$selection->fetchPairs('name', 'count'); //vrati [nazev => pocet, ...]
Chvíli trvá, než si na to člověk zvykne, ale je dost navýkový;)
Editoval Caine (8. 5. 2012 10:28)
- Caine
- Člen | 216
Tady z forá resp. z videa z poslední soboty (https://forum.nette.org/…ledni-sobote). Ty videa doporučuju, je tam dost věcí, který v dokumentaci pořád chyběj.
- motorcb
- Člen | 552
Caine napsal(a):
V nette\database se join vytváří automaticky, stačí psát jen jaký tabulky se v dotazu použijou (např. bazar.id, resp bazar:id) a v závislosti na použitý reflexi, se sami doplněj joiny. Pro takovej dotaz by mělo stačit následující.
$selection = $connection->table('bazar_category')->select('name')->select('COUNT(bazar:id) AS count')->group('bazar_category_id'); //dvojtecka u bazar:id je backjoin, bazar odkazuje na kategorii, //pokud by tam byla tecka, snazilo by se to udelat join s tim, //ze kategorie odkazuje na bazar (coz je blbost). foreach ($selection as $row) { echo $row->name . ': ' . $row->count; } //nebo $selection->fetchPairs('name', 'count'); //vrati [nazev => pocet, ...]
Chvíli trvá, než si na to člověk zvykne, ale je dost navýkový;)
Díky za info ale co dosadím za $connection ???
S
$this->context->table(‚bazar_category‘)->select(‚name‘,
‚href‘)->select(‚COUNT(bazar:id) AS
count‘)->group(‚bazar_category_id‘); mi to nefunguje :(
Hlásí to:
Call to undefined method SystemContainer::table().
- motorcb
- Člen | 552
jtousek napsal(a):
Tak možná $this->context->database… prostě název služby Nette\Database\Connection, to bys měl vyčíst někde v configu.
Super, tak tohle funguje skvele:
$this->context->database->table('bazar_category')->select('name, href')->select('COUNT(bazar:id) AS count')->group('href')->order('bazar_category.id')
Jen bych ještě potřeboval z toho dotazu získat počet záznamů
v tabulce bazar, které nejsou starší než 7 dní (sloupec date). Nevěděl
by někdo?
Protože když přidám do dotazu další select a where, tak se where aplikuje
na celý dotaz, já bych ho potřeboval aplikovat pouze na zvolenou
část :(
$this->context->database->table('bazar_category')->select('name, href')->select('COUNT(bazar:id) AS count')->group('href')->order('bazar_category.id')->select('COUNT(bazar:id) AS countNew')->where()
Díky
- vvoody
- Člen | 910
motorcb napsal(a):
Jen bych ještě potřeboval z toho dotazu získat počet záznamů v tabulce bazar, které nejsou starší než 7 dní (sloupec date). Nevěděl by někdo?
Protože když přidám do dotazu další select a where, tak se where aplikuje na celý dotaz, já bych ho potřeboval aplikovat pouze na zvolenou část :($this->context->database->table('bazar_category')->select('name, href')->select('COUNT(bazar:id) AS count')->group('href')->order('bazar_category.id')->select('COUNT(bazar:id) AS countNew')->where()
Z toho popisu nemam ponatia co presne chces :) ale ked potrebujes polozit odlisny dotaz tak jednoducho zacni od znovu
$this->context->database->table('bazar_category')->....
Ohladne tej podmienky nad stlpcom date, skus toto:
$days = 7;
$date = new DateTime(); //now
$date->sub(new DateInterval('P'.$days.'D')); //now - 7 days
$selection->where('date > ?',$date);
- motorcb
- Člen | 552
vvoody:
Jde mi o to abych vypsal „Název kategorie ( počet všech příspěvků
v kategorii / počet příspěvků za poslední týden)“
Ohladne tej podmienky nad stlpcom date, skus toto:
$days = 7; $date = new DateTime(); //now $date->sub(new DateInterval('P'.$days.'D')); //now - 7 days $selection->where('date > ?',$date);
Kdybych položil samostatný dotaz, jak bych ho spároval z původním
dotazem?
Abych k názvu kategorie vypsal správný počet záznamů za
poslední týden?
Díky
- petr.pavel
- Člen | 535
Polož dva dotazy (clone $selection). Mohl bys to sice nějak hackovat přes subquery nebo IF v SQL, ale takhle to bude čistější a nejspíš i rychlejší.
Edit: Dva myslím jako jeden pro celkový počet, druhý pro počet za poslední týden.
Editoval petr.pavel (14. 5. 2012 10:28)
- petr.pavel
- Člen | 535
Přes PHP (ber s rezervou, píšu z hlavy a sám místo NTB používám NotORM):
$vsechny = $this->context->database->table('bazar_category')->select('bazar_category.id, name, href, COUNT(bazar:id) AS pocet')->group('href')->order('bazar_category.id');
$zaTyden = clone $vsechny;
$zaTyden = $zaTyden->where('date > ?',strtotime("-1 week"))->fetchPairs('id', 'pocet');
foreach ($vsechny as $radka) {
$radka['pocetTyden'] = 0;
if (isset($zaTyden[ $radka['id'] ])) {
$radka['pocetTyden'] = $zaTyden[ $radka['id'] ];
}
}
- motorcb
- Člen | 552
Tak by pro mne bylo nejlepší to psát přes vložený dotaz.
Dokázal by někdo přepsat tento dotaz do ORM?
Jde to vůbec?
SELECT bc.name, bc.href, bc.id, COUNT(b.id) AS count, ( select count(*) from bazar b2 where bc.id = b2.bazar_category_id and date > 123456789 ) as countNew
FROM bazar_category bc
LEFT JOIN bazar b ON bc.id = b.bazar_category_id
GROUP BY href
ORDER BY bc.id
- petr.pavel
- Člen | 535
@motorcb: Ono se zdá pohodlnější zůstat u starého způsobu uvažování a skládat si dotazy sám, ale uvaž, proč jsi vůbec šel do NTD/NotORM. To's přece mohl zůstat u Dibi.
Doporučoval bych ti přečíst důvody, které měl Jakub Vrána k vytvoření NotORM. Případně srovnání rychlosti. Ostatně, Jakubův blog obsahuje i další články, které by ti mohly objasnit smysl a vnitřní chody NotORM (a tudíž i NTD).