Autor | Zpráva | ||
---|---|---|---|
Sir Tom Profil |
#1 · Zasláno: 17. 6. 2011, 18:47:26
Ahoj, v MySQL mám tabulku "sections" se sloupci ID, name, level, parentID. Každá položka zde obsahuje level 1,2, nebo 3, kde 1 značí nejvrchnější level a 3 nejnižší a sloupec parentID, kde je napsáno k jaké položce je tato položka podřízena. Chci vypsat všechno záznamy tak, aby pod každou položkou, která je rodičem se objevily položky (potomci) o level nižší. Uvedu příklad:
Záznamy v tabulce: ID,name,level,parentID; 1,"rok 2009",1,0; 2,"rok 2010",1,0; 3,"rok 2011",1,0; 4,"duben",2,1; 5,"červen",2,2; 6,"2. pondělí",3,4; Výstup by měl vypadat takto: rok 2009 duben 2. pondělí rok 2010 červen rok 2011 Poradíte mi, prosím, nějaký pěkný MySQL dotaz? Napadlo mě použít 3 vnořené dotazy, ale to mi nepřijde jako efektivní metoda. |
||
TomášK Profil |
#2 · Zasláno: 18. 6. 2011, 00:58:59
Sir Tom:
Můžeš si vybrat z následujících řešení: * vybrat z databáze vše a řešit to na úrovni aplikace * změnit strukturu uložení dat (hledat traverzování kolem stromu) * změnit databázi na nějakou, která umí rekurzivní dotazy Pokud vím, na úrovni MySQL to při stávající struktuře nejde elegantně vyřešit. |
||
Sir Tom Profil |
#3 · Zasláno: 18. 6. 2011, 22:51:03
TomášK:
„změnit strukturu uložení dat (hledat traverzování kolem stromu)“ Děkuji, nastuduji tento způsob. O tomto jsem vůbec nevěděl, aspoň se dozvím něco nového. :) |
||
Alphard Profil |
#4 · Zasláno: 18. 6. 2011, 23:08:25
Teorie je např. na http://interval.cz/clanky/metody-ukladani-stromovych-dat-v-relacnich-databazich/
Prakticky potom nejlépe na http://php.vrana.cz/traverzovani-kolem-stromu-prakticky.php Je to časný problém. Začátečníci vymyslí ukládání parent id (nebo to radí na nějakém známém webu?) a pak nevědí, jak dál... |
||
TomášK Profil |
#5 · Zasláno: 18. 6. 2011, 23:37:11
Alphard:
„Je to časný problém. Začátečníci vymyslí ukládání parent id (nebo to radí na nějakém známém webu?) a pak nevědí, jak dál...“ Nelíbí se mi, že z toho příspěvku vyznívá, že použití parent_id je špatný návrh databáze. Podle mě návrh pomocí parent_id je ten správný a používání odkazovaného uložení je workaround, jak to řešit, že databáze nemá rekurzivní dotazy. Přijde mi to, jak ukládání počtu položek, kdyby databáze neuměla efektivně COUNT(*). Analogie funguje i v tom, že někdy může být 'méně pěkné' řešení lepší z důvodu optimalizace i v databázi, která umožňuje obě možnosti (a rozdíl nebude velký, ani lft, rgt ani ruční ukládání počtu položek jsem snad zatím z optimalizačních důvodů nepoužil). |
||
Alphard Profil |
#6 · Zasláno: 18. 6. 2011, 23:56:12
TomášK:
„Nelíbí se mi, že z toho příspěvku vyznívá...“ Měl jsem si to asi odpustit :-), trochu jsem doufal, že právě zjistím příčinu. 99 % dotazů se tady týká MySQL a tazatelé s ním pracují, takže rekurzivní dotazy prostě nejsou k dispozici. Menší datové sady lze řešit rekurzivně s pomocí PHP, ale je jasné, že výkon klesá docela rychle. V dané situaci je traverzování kolem stromu asi nejlepší možnosti. Prostě denormalizace z praktických důvodů, nebudu stavět teoreticky dokonalou relační databázi, ze které nedostanu data (zřejmá nadsázka, nebrat doslova). Objektivní hodnocení jednotlivých metod je v odkázaném článku, včetně informací o tom, že přesunout uzly ve stromě není zrovna jednoduché. |
||
okolojdouci Profil * |
#7 · Zasláno: 19. 6. 2011, 00:08:15
Alphard:
„Menší datové sady lze řešit rekurzivně s pomocí PHP, ale je jasné, že výkon klesá docela rychle.“ Jen bych pro představu doplnil, že při té logice, která je uvedena v #1, je získání dat z databáze nepoužitelně pomalé už při 500 položkách - jde o sekundy. |
||
TomášK Profil |
#8 · Zasláno: 19. 6. 2011, 02:20:39
Alphard:
Souhlasím, že pro MySQL je to zřejmě nejlepší řešení - jak říkáš, denormalizace z praktických důvodů. Nepřekvapuje mě, že struktura s parent_id je to, co navrhují ti, co na tenhle problém zatím nenarazili. Jedná se o běžné použití cizího klíče, jen je cílová tabulka shodná se zdrojovou. Pokud někdo používá cizí klíče, je tohle přesně struktura, která ho napadne. Traverzování kolem stromu nenapadne při prvním použití snad nikoho - pokud si o ní nepřečte článek. okolojdouci: Uvedená čísla jsou zřejmě pro hodně pomalou implementaci. Zkusil jsem si napsat kod, který vygeneruje strom - pole s položkami (id, parent_id), zamíchá ho a poté vypíše tak, jako se vypisuje menu. Včetně vygenerování a setřídění to na 1000 položkách trvá 0.03s. Pro 50 000 položek to trvá ~1sec. |
||
okolojdouci Profil * |
#9 · Zasláno: 19. 6. 2011, 03:03:38
TomášK:
„Uvedená čísla jsou zřejmě pro hodně pomalou implementaci“ Uf, tak to se omlouvám. Netestoval jsem to nějak podrobně, skládám z toho menu, které se rozbaluje javascripem, tak ta prodleva může vznikat tam. |
||
Sir Tom Profil |
#10 · Zasláno: 19. 6. 2011, 09:47:41
TomášK:
„Traverzování kolem stromu nenapadne při prvním použití snad nikoho - pokud si o ní nepřečte článek.“ Ano - předtím jsem to neznal. Jaksi jsem ale stejně počítal s tím, že id a parent_id nebude to pravé ořechové... navíc nic jiného mě nenapadlo a už vůbec ne, že bych měl do vyhledávače napsat "traverzování kolem stromu". Ona tabulka bude mít max. 100 záznamů. Alphard: Díky za odkazy, ale již jsem si je našel předtím. |
||
Časová prodleva: 13 let
|
0