Při ->group(…)->count(„*“) se volá dotaz bez GROUP BY
- Robyer
- Člen | 74
Používám Nette\Database v aktuálním Nette 2.1.0 s MYSQL databází.
Mám připravené table selection třeba takto:
$res = $db->table("tabulka")->select(...)->group("sloupec");
Když chci spočítat celkový počet řádků pro paginator pomocí
->count("*")
, tak se v dotazu „ztratí“ GROUP BY a vrátí
se počet všech řádků (vykoná se
SELECT COUNT(*) FROM `tabulka
`).
Dělám něco špatně nebo je chyba v Nette\Database? Existuje případně workaround jak takový dotaz vykonat správně?
EDIT: Tak zřejmě je to bug:
Buď by to mělo nahradit všechny group() za DISTINCT v selectu a vrátit count takto,nebo by to mělo vyhodit výjimku, že nad takovým Selection nelze provádět ->count(„*“)- Mělo by to použít poddotaz (viz níže)
V souvislosti s tím pak nefunguje správně ani metoda page() – https://api.nette.org/…ion.php.html#…
Editoval Robyer (28. 1. 2014 9:35)
- Robyer
- Člen | 74
@hrach Zaznamenávám si vyhledávané fráze na stránkách a pak je chci zobrazit v administraci v tabulce, seskupené dle četnosti jednotlivých hledání.
$items = $this->table("log_search")->select("word, COUNT(*) AS cnt, AVG(results) AS avg")->group("word");
Potom mám v presenteru obecnou metodu, která mi připravuje paginator. Té dám Selection, ze kterého zjistí počet řádků a aplikuje na ni limit.
...
$paginator->itemCount = $items->count("*");
$items->limit($paginator->itemsPerPage, $paginator->offset);
...
Mohl bych si samozřejmě napsat ten dotaz pro získání počtu řádků ručně, ale v tom případě bych očekával, že na mě při volání count(„sloupec“) nad grouped selection vyskočí výjimka (protože takhle se jen tiše vrátí špatný/neočekávaný výsledek).
- Robyer
- Člen | 74
Pravda, řešení od @nanuqcz se subdotazem je optimální, mé 2 návrhy jsou nesmysl, díky :)
Tedy když bude ->count("*")
nad grouped selection, mělo by
se to obalit a použít jako subdotaz, např:
SELECT COUNT(*)
FROM (
SELECT `id`
FROM `article`
GROUP BY `article`.`id`
HAVING `id` > 5
) counted_table
@hrach Co si o tom myslíš?
- Robyer
- Člen | 74
Tak pokud by někdo měl stejný problém jako já, může použít tento workaround:
/**
* Workaround for broken count("*") in Nette\Database in grouped selection
*/
public function getSelectionCount(\Nette\Database\Table\Selection $items) {
if ($items->getSqlBuilder()->getGroup()) {
$query = "SELECT COUNT(*) FROM (" . $items->getSql() . ") AS _";
$parameters = $items->getSqlBuilder()->getParameters();
$row = $this->database->queryArgs($query, $parameters)->fetch();
return $row[0];
} else {
return $items->count("*");
}
}
Editoval Robyer (28. 1. 2014 9:40)