Autor Zpráva
maarlin
Profil
Mám běžnou strukturu kategorií, která se celá dá získat rekurzí.
id | name      | parent_id
--------------------------
 1 | Notebooky | 0
--------------------------
 2 | 15.4      | 1

a na to navázanou tabulku zboží, která je logicky navázaná na sloupec id.
Když chci vypsat zboží z nějaké z kořenových kategorií (tj. kategorie, která má id=0), musím se doptat pokaždé na příslušné vnořené kategorie (děti té kořenové kategorie).
<?php
function findAllChildrenIds($categoryId, $data=array())
{
	$data[] = $categoryId;
	$category = $this->connection->select('*')->from($table)
		->where('parent_id=%i', $categoryId)->fetchAll();
	if (count ($category) > 0) {
		foreach ($category as $cat) {
			$this->findAllChildrenIds($cat->id, &$data);
		}
	}
	return $data;
}
?>

a pak je dosadit do dotazu, který mi vybere to patřičné zboží (samozřejmě tam je ještě implode):
SELECT * FROM products WHERE category_id IN ($childrenIds)

Postup sice relativně funguje, ale generuje nesnesitelné množství dotazů a tomu úměrný potřebný čas na zpracování (>4s), což se mi moc nelíbí.
Nevíte prosím někdo, jak by se dal tento dotaz přepsat do jednoho, popř. dvou (třeba nějak za použití SQL proměnných)?
Kajman_
Profil *
Mrkněte na využití pomocných předpočítaných sloupců, které takové dotazy urychlí.

http://dev.mysql.com/tech-resources/articles/hierarchical-data.html
http://interval.cz/clanky/metody-ukladani-stromovych-dat-v-relacnich-databazich/
http://php.vrana.cz/traverzovani-kolem-stromu-prakticky.php
maarlin
Profil
Kajman:
Mrkněte na využití pomocných předpočítaných sloupců, které takové dotazy urychlí.
>
http://dev.mysql.com/tech-resources/articles/hierarchical-data.html
http://interval.cz/clanky/metody-ukladani-stromovych-dat-v-relacnich-databazich/
http://php.vrana.cz/traverzovani-kolem-stromu-prakticky.php
Díky, už jsem četl, jen jsem to zapomněl zmínit. Důvod, proč tam ponechávám "rekurzivní" strukturu je ten, že se mnoho kategorií často aktualizuje, resp. synchronizuje a ta synchronizace by v případě využití "traverzování" byla neskutečnou zátěží... představte si třeba 100 nových kategorií připravených k přidání a starých 1500... to máme 1500*100 přepočítání (=dotazů) celé tabulky... V takovém případě bych už snad i oželel ty 4sec při čtení z tabulky.
Kajman_
Profil *
představte si třeba 100 nových kategorií připravených k přidání a starých 1500

Když vím, že budu dávat tolik nových, tak je přidám a teprve po všech přepočítám podle parent_id nové lft a rgt, tak to máte 1600 updatů jednoho řádku a selectů max 1600 (když bude 1600 úrovní).

Jinak k původnímu dotazu, pokud traverzování není vhodné, tak pro 1600 kategoríí bych si asi udělal pole všech kategorí v php a v něm rekurzivně našel všechny id potomků a ty použil v dotaze.
ninja
Profil
SELECT * FROM products JOIN kategorie k1 ON category_id=k1.id LEFT JOIN kategorie k2 ON k1.parent_id=k2.id ... WHERE $categoryId_id IN (k1.id, k2.id, ...);


Nevýhoda tohoto řešení je zřejmá, ale pokud jste schopen limitovat počet zanoření na nějakou rozumnou úroveň, je to použitelné.
TomášK
Profil
Některé databáze podporují rekurzivní dotazy, od loňska i PostgreSQL. Jste-li vázán na MySQL, pak nezbývá než použít jiné řešení.

Vaše odpověď

Mohlo by se hodit

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: