Agregační podmínka na jinou tabulku

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

Ahoj,
dejme tomu, že bych chtěl z DB získat všechny kategorie, které obsahují nějaké itemy.

Bohužel dotaz

$database->table('category')->where('COUNT(item:id) > 0');

skončí chybou.

Zatím mám tedy toto:

$database->table('category')->where('id',
	$database->table('item')->select('DISTINCT category_id')
);

ale víc by se mi líbilo, kdyby fungovala první možnost. Je chyba v Nette\Database, anebo na to jdu špatně?

Díky

Editoval nanuqcz (10. 6. 2012 16:16)

jtousek
Člen | 951
+
0
-

Jakou chybu hlásí ten první dotaz?

Zkusím trochu střelit od boku:

$database->table('category')->select('COUNT(item:id) AS count')->where('count > 0');
nanuqcz
Člen | 822
+
0
-
PDOException #HY000
SQLSTATE[HY000]: General error: 1111 Invalid use of group function

SELECT `category`.*
FROM `category`
INNER JOIN `item` ON `category`.`id` = `item`.`category_id`
WHERE (COUNT(`item`.`id`) > 0)

Tvůj dotaz vyhodí trochu jinou chybu:

PDOException #42S22
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'count' in 'where clause'

SELECT COUNT(`item`.`id`) AS `count`
FROM `category`
LEFT JOIN `item` ON `category`.`id` = `item`.`category_id`
WHERE (`count` > 0)

což už nechápu vůbec, protože podle mě to SQL vypadá vpořádku.

Tomáš Votruba
Moderator | 1114
+
0
-

COUNT je myslím rezervovaný výraz (jako ORDER), zkus třeba item_count.

Editoval Schmutzka (10. 6. 2012 17:34)

Nifty
Člen | 45
+
0
-

Rezervovaným výrazem to není. Na alias nelze použít podmínka WHERE (teda alespoň v MySQL). Nedávno jsem to taky řešil ve svém Gridu a nakonec na alias používám podmínku HAVING.

V Nette\Database to lze provést takto

$database->table('category')->select('COUNT(item:id) AS count')->group(NULL, 'count > 0');
llook
Člen | 407
+
0
-

Nejdřív se provede výběr podle WHERE a na něm se teprve provádí agregační funkce (COUNT). Jinak jestli chceš vybrat všechny kategorie, které mají alespoň jeden příspěvěk, tak udělej RIGHT JOIN a potom GROUP BY:

SELECT *
FROM `category`
RIGHT JOIN `item` ON `category`.`id` = `item`.`category_id`
GROUP BY `category`.`id`

Jak to zapsat v Nette\Database ale teď nevím.

bojovyletoun
Člen | 667
+
0
-

a zkoušel jsi tedy nahradit where za having v první ukázce?

jtousek
Člen | 951
+
0
-

bojovyletoun napsal(a):

a zkoušel jsi tedy nahradit where za having v první ukázce?

To by nestačilo. Před having musí být group by.

Nifty
Člen | 45
+
0
-

Nějak jsem zapomněl, že tam používá agregační funkci. V tom případě ve group nebude NULL, ale

$database->table('category')->select('COUNT(item:id) AS count')->group('category.id', 'count > 0');

(jinak HAVING funguje i bez GROUP BY, pokud se použije alias například na duplicitní název sloupce v připojené tabulce)

Editoval Nifty (10. 6. 2012 19:51)

nanuqcz
Člen | 822
+
0
-

Díky moc, funguje ;-)

$database->table('category')->select('category.*, COUNT(item:id) AS count')
	->group('category.id', 'count');