Autor | Zpráva | ||
---|---|---|---|
Sylar Profil |
#1 · Zasláno: 18. 11. 2013, 15:59:16
Zdravím,
mám takovéto pole ( [0] => Array ( [id] => Array ( [orig] => 1171 ) [par_id] => Array ( [orig] => 0 ) [nazev] => Array ( [orig] => "Položka 1" ) ) [1] => Array ( [id] => Array ( [orig] => 2000 ) [par_id] => Array ( [orig] => 0 ) [nazev] => Array ( [orig] => "Položka 2" ) ) [2] => Array ( [id] => Array ( [orig] => 1190 ) [par_id] => Array ( [orig] => 1171 ) [nazev] => Array ( [orig] => "Položka 3" ) ) ) Potřeboval bych seřadit položky, které mají nenulový údaj [par_id][orig] a zařadit je tak, aby byly ihned za polem, které odpovídá [par_id][orig] == [id][orig] . Jedná se o strom položek, kdy údaj [par_id][orig] nese ID rodičovské položky a já bych potřeboval pole seřadit tak, aby byla hlavní položka a ihned za ní, aby byly její dceřiné (jsou-li nějaké), za nimi další hlavní položka a za ní opět (má-li nějaké) dceřiné položky. Pořadí hlavních položek (tedy těch, které mají [par_id][orig] == 0) musí zůstat nezměněné (vůči ostatním hlavním položkám) . Ukázkové pole výše by tedy mělo po seřazení být v pořadí [Položka 1], [Položka 3], [Položka 2] |
||
mzk Profil * |
#2 · Zasláno: 18. 11. 2013, 20:57:27
Sylar:
> Zdravím, > mám takovéto pole otázkou je, kde se to pole bere? nešlo by to pole už rovnou vytvářet dle tvých požadavků, než ho pak seřazovat? |
||
Sylar Profil |
#3 · Zasláno: 18. 11. 2013, 21:49:56
mzk:
beru jej z databáze, kde jsou všechny položky uloženy v jedné tabulce se sloupci [ID] [PAR_ID] [NAZEV] , provázanost mezi ID a PAR_ID je stejná jako popisuji výše. Přemýšlel jsem nad tím, ale pokud lze takto seřadit pole pomocí sql dotazu, je to bohužel nad mé znalosti. Osobně si myslím, že to ale asi nepůjde. |
||
Tori Profil |
Řešila bych to určitě na úrovni databáze. Pro větší objem dat to bude IMHO i rychlejší, než přeskládávat pole v PHP.
SELECT id, par_id, IF(par_id == 0, id, par_id) ref, nazev FROM tabulka ORDER BY ref, (par_id == 0) DESC, nazev Pokud byste tedy chtěl řadit i rodiče podle názvu, bude potřeba poddotaz, něco jako SELECT r.id, r.nazev, p.id AS idPotomka, p.nazev AS nazevPotomka FROM (SELECT id, nazev FROM tabulka WHERE par_id = 0 ORDER BY nazev) r LEFT JOIN tabulka p ON r.id = p.par_id ORDER BY r.nazev, r.id, p.nazev ORDER BY r.nazev, p.nazev .
edit: Předpokládám, že je to jen dvouúrovňová struktura. |
||
Sylar Profil |
#5 · Zasláno: 20. 11. 2013, 02:40:42
Tori:
díky za nápad, jen tam moc nechápu ten poddotaz, opravdu má být v klauzuli FROM? Mohla bys mi prosím spíše popsat myšlenku toho druhého řešení s podvýrazem, asi mi něco důležitého uniká a nevidím tam to řešení. |
||
Tori Profil |
#6 · Zasláno: 20. 11. 2013, 14:46:37
Sylar:
„opravdu má být v klauzuli FROM?“ Ano. Zkusil jste to, jaká data vám ten dotaz vrátí? Princip je ten, že mám (dejme tomu na nějakém fóru) tabulku r s tématy (= rodiče, r.par_id == 0), a k ní připojím druhou tabulku p s příspěvky (= potomci, p.par_id == rodič.id). Akorát tu první tabulku nemáte samostatně, tak si ji musíte vytvořit poddotazem. |
||
Sylar Profil |
Tori:
zkoušel, ale hodilo mi to chybu, že tabulka "r" neexistuje, resp. že neexistuje sloupec "r.id" . Princip je ten, že mám (dejme tomu na nějakém fóru) tabulku r s tématy (= rodiče, r.par_id == 0), a k ní připojím druhou tabulku p s příspěvky (= potomci, p.par_id == rodič.id). Tomuhle rozumím, ale nebude potíž v tom, že v klauzuli FROM vybíráme sloupce "id" a "název" a dotaz tam očekává pouze jméno té tabulky? Edit: Ještě jsem zde nezmínil, možná, že to není důležité, že data si uživatel může řadit i podle dalších sloupců (např. cena apod. - další sloupce jsem do tohoto příkladu neuváděl kvůli zjednodušení), takže při selectu by se měla nejprve podle konkrétního sloupce (např. cena) seřadit nejprve rodiče a k nim poté vybrat děti (ty by se v ideálním případě také mohli řadit dle ceny, ale to už za každou cenu být nemusí). |
||
Tori Profil |
Sylar:
„hodilo mi to chybu, že tabulka "r" neexistuje, resp. že neexistuje sloupec "r.id" .“ Udělala jsem si pokusnou tabulku, dotaz mi chybu neháže. Jak vypadá váš dotaz, se správnými názvy tabulek atd.? edit: A v tom poddotazu je řazení zbytečné, stačí řadit až výsledek spojení tabulek (nemůžu to už opravit ve [#4].) |
||
Sylar Profil |
#9 · Zasláno: 20. 11. 2013, 16:48:19
Tori:
tak ta chyba byla způsobena zřejmě něčím jiným, omluva - moje chyba. Nyní mi dotaz vyhodí pouze potomky: SELECT r.id AS par_id, r.nazev AS par_nazev, p.id, p.nazev FROM (SELECT id, nazev FROM udaje WHERE par_id = '0') r LEFT JOIN udaje p ON r.id = p.par_id ORDER BY r.nazev, r.id, p.nazev Array ( [0] => Array ( [par_id] => 310 [par_nazev] => Název [id] => 311 [nazev] => Název ) [1] => Array ( [par_id] => 310 [par_nazev] => Název [id] => 812 [nazev] => Název ) [2] => Array ( [par_id] => 310 [par_nazev] => Na skok do Paříže [id] => 800 [nazev] => Na skok do Paříže ) ) Neukáže se rodič [ID = 310] a několik dalších rodičů bez potomků. |
||
Tori Profil |
#10 · Zasláno: 20. 11. 2013, 18:03:32
No, mě totiž nenapadlo, jak udělat to "za rodičem následují jeho potomci" - možná s tím počítáte při čtení z DB? Můj dotaz vrací vždycky ve stejném řádku s rodičem i jeho prvního potomka, takže tady by to mělo vyhodit něco jako:
par_id | par_nazev | id | nazev | 310 | Název | 311 | Název | -- tady začíná rodič ID 310 + zároveň jeho první potomek. 310 | Název | 812 | Název | -- další potomek rodiče ID 310 310 | Název | 800 | Na skok... | -- dtto 123 | Něco | NULL | NULL | -- tady začíná rodič ID 123, který nemá žádného potomka 456 | Nadpis | NULL | NULL | -- další rodič, s ID 456, taky bez potomka |
||
Sylar Profil |
#11 · Zasláno: 21. 11. 2013, 17:05:29
Tori:
tak nakonec jsem to vyřešil ještě jinak, přeskládáním pole. Script prochází celé pole a zjistí zda-li je prvek dítě nebo rodič. Pokud dítě, projde znova celé pole a najde rodiče. Poté posune všechny položky vzad či vpřed (záleží jestli se dítě nachází před nebo za rodičem) a na volné místo umístí dítě. Pokud rodiče nenajde, nechá dítě tam kde je. $last_id = 0; for($i = 0; $i < count($data); $i++) { $item = $data[$i]; if ($item['par_id'] == 0) { $last_id = $item['id']; continue; } if ($last_id == $item['par_id']) { continue; } foreach($data as $d => $dat) { if ($item['par_id'] == $dat['id']) { if ($i < $d) { for($j = $i; $j < $d; $j++) { $data[$j] = $data[$j + 1]; } $empty = $d; $i -= 1; } else { for($j = $i; $j > $d; $j--) { $data[$j] = $data[$j - 1]; } $empty = $d + 1; } $data = $item; } } } |
||
Časová prodleva: 10 let
|
0