Nette Database ->related()->where()->count() a počet dotazů

Yaromil
Backer | 20
+
0
-

Ahoj,

řeším velký počet zbytečných (= duplicitních) dotazů do databáze při použití ->related()->where(). Následující kód generuje pouze jeden dotaz do DB:

foreach ($data as $row) {
  echo $row->related('team_member')->count();
}

ale následující, kde je i potřebná podmínka where() vygeneruje tolik dotazů, kolik je záznamů v poli $data, tedy pro každý průchod foreach jeden:

foreach ($data as $row) {
  echo $row->related('team_member')->where('team_id', $row->id)->count();
}

Dokázal bych to pochopit, protože podmínka je jedinečná pro každý průchod foreach, ALE do DB je odesláno X identických dotazů, které se absolutně neliší, proto mi to hlava úplně nebere,… proč se tomu tak děje.

Dokázal by někdo prosím poradit, jestli dělám něco špatně nebo jak se těm vícenásobným dotazům vyhnout?

Díky!

Editoval Yaromil (20. 11. 2019 14:35)

Mysteria
Člen | 797
+
+1
-

Místo ->count() použij ->count('*'). Netuším jestli to redukuje počet dotazů, ale ten první vytáhne všechny záznamy z databáze a spočítá je až v PHPku, kdežto ten druhej zavolá přímo SELECT COUNT(*) což je mnohem efektivnější.

Martk
Člen | 652
+
+1
-

Budeš muset udělat tohle:

$counts = $db->table('team_member')->select('COUNT(team_id) AS count, team_id')->where('team_id IN(?)', array_map(fn ($row) => $row->id, $data))->fetchPairs('team_id', 'count');

foreach ($data as $row) {
	echo $counts[$row->id];
}

nebo tak nějak, nette db jsem nepoužil hodně dlouho

Yaromil
Backer | 20
+
0
-

Díky oběma za doporučení.

->count(‚*‘) bohužel nepomohlo, ale každopádně díky za radu.

Nakonec jsem (dočasně) vyřešil počítáním na straně PHP, což není ideální, ale přišlo mi to trochu čitelnější řešení než to, které navrhoval Martk.

$count = 0;

foreach ($row->related('team_member') as $member) {
  if ($member->team_id == $row->id) {
    ++$count;
  }
}