Diskuze: Rekurzivní počítání článků v sekcích
V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.

Vlastník

Zobrazeno 20 zpráv z 20.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.
Rekurze se v SQL dělá blbě, resp. nedá se udělat efektivně. Asi to bude chtít mírnou denormalizaci a přidat do podsekcí sloupec s počtem článků. Tento sloupec pak aktualizovat např. triggerem při manipulaci s články.
Díky za reakci. Toto řešení nás napadlo, ale když došlo na
implementaci, nějak jsme se na tom zasekli, mám hrozně nerekurzivní
myšlení Hlavně nevím, jak
to obnovovat, předpokládám, že celé najednou by to trvalo dlouho, čili
bychom potřebovali metodu, která nám refreshne počet článků u 1 sekce a
všech jejich nadsekcí. Znamená to, že máme udělat refresh té jedné sekce
a potom si hodit querku, jestli ta sekce není náhodou do nějaké vnořená a
pokud ano, celou akci opakovat? Naštěstí máme vazbu sekce-článek jen
1:N.
Hlavně mi tam chybí hodně informací, možná bych to potřeboval nejdříve celé spočítat nějakým skriptem a dalším jen refreshovat jednu sekci, co se změnila.
Myslel jsem to tak, že by se např. při přidání článku do sekce inkrementoval čítač v sekci, následně by se inkrementoval i čítač v nadřízených sekcích až ke kořeni.
Bohužel na takové opičky nejsou SQL databáze stavěny. Jedině snad přes ten trigger.
Ještě mě napadla jedna varianta: Natáhnout seznam sekcí (stačí jen id a parent_id), průchodem od listu ke kořeni vybrat id sekcí (např. 5, 18, 200) a pak už jen
UPDATE sekce SET pocet=pocet+1 WHERE id IN (5, 18, 200);
Zkusil jsem to udělat tím triggerem, ale bohužel nezvládne rekurzi.
Ještě doplním, že v SQLite to s tím triggerem funguje parádně.
Ony právěže ty sekce nemají parrent_id. Musím to nějak denormalizovat asi. Současný stav je následující:
tabulka sekce obsahuje sekce spolu s informací v jakém jazyce jsou zdrojové kódy v sekci. Dále je tu odkaz na článek, který sekci reprezentuje.
článek má potom informaci do které sekce patří (což
může jako článek obyčejný i jako článek reprezentující sekci). Čili
já z tabulky sekcí nezjistím, kdo je rodič, musím tam najoinovat článek.
A to jsem chtěl ještě vazbu rozšířit na M:N, to by to už asi úplně
pohřbilo
Viděl bych to na zrušení tabulky sekce. Informace o sekcích by pak byly jako další záznamy mezi články. Článek by měl své id a parent by označoval sekci. Sekce by měla své id a parent by odkazoval na nadřízenou sekci. Nejvyšší sekce by měly parent=null.
Jen tak pro zajímavost malá ukázka, jak to funguje v SQLite.
PRAGMA recursive_triggers = on;
CREATE TABLE sekce(id integer primary key autoincrement, parent int, nazev text, pocet int);
INSERT INTO "sekce" VALUES(1,NULL,'PHP',0);
INSERT INTO "sekce" VALUES(2,NULL,'C#',0);
INSERT INTO "sekce" VALUES(3,8,'Java',0);
INSERT INTO "sekce" VALUES(4,1,'Databaze v PHP',0);
INSERT INTO "sekce" VALUES(5,1,'Vyjimky v PHP',0);
INSERT INTO "sekce" VALUES(6,3,'Java na desktopu',0);
INSERT INTO "sekce" VALUES(7,3,'Java na serveru',0);
INSERT INTO "sekce" VALUES(8,NULL,'sekce pro Javu',0);
CREATE TRIGGER tr_sekce UPDATE OF pocet ON sekce
BEGIN
UPDATE sekce SET pocet=pocet-old.pocet+new.pocet WHERE sekce.id=old.parent;
END;
Při aktualizaci pocet
např. u id
=7 se aktualizuje
i id
=3 a 8.
A nebude to moc denormalizované? Sekce bude mít navíc počet článků
uvnitř, titulek (je často jiný, než článku), jazyk a ještě jsem
plánoval další vlastnost, která by určovala od jakého čísla číslovat
články. Tak by se daly udělat navazující seriály přes několik sekcí a
šlo by mezi díly jednoduše řadit další bez nutnosti manuálního
přečíslování. To jsou 4 prázdné sloupce u většiny článků, už teď
jich má 25
Na tu vazbu M:N se tedy asi vykašlu, ušetří to hodně problémů a
nechceme jen psát redakční systém
Počet článků bude u článku roven 1, sloupec s titulkem bude sdílený (sekce je v jiném záznamu) jazyk by měl být u každého článku, číslování článků je zdrojem problémů. Tedy bez prázdného sloupce.
Z článku se snadno může stát sekce. To nezní špatně.
Navazující seriály se dají udělat přes URL v článku či sekci.
Sekce jsou uzly a články jsou listy stromu. V principu není velký rozdíl mezi uzlem a listem a sjednocení přístupu zpravidla vede ke zjednodušení aplikace.
A jakým způsobem udělám naplnění toho počtu článků v sekci poprvé,
když bude ten sloupec ještě prázdný? Nějak mě nenapadá za který konec
to vzít
Číslování článků mi tu chybí i když je to další komplikace, ty seriály by lépe vynikly. Máme sloupec, kde je pořadové číslo článku v sekci (tak jim určujeme pořadí výpisu, máme javascriptový widget, kde je myší seřadíme a on je tak očísluje), asi by se to dalo využít pro tento účel a s omezením, že by samostatné články nebyly mezi lekcemi, by to mohlo docela fungovat.
To nebude zas tak složité. Záleží na tom, jestli do tabulky prvně uložíš sekce nebo články. Případně tam dáš všechno, necháš to propočítat a aktivuješ trigger.
Číslování článků můžeš udělat ve výstupní šabloně, v DB to být nemusí. Alespoň nebudeš muset řešit přečíslování.
Číslování sekcí by také mohlo mít svůj význam.
No já nevím jak to nechat propočítat Potřeboval bych začít od těch
nejnižších sekcí, ale jak je poznám?
V šabloně by to šlo v seznamu článků, ale když si ho otevřu, ten článek už neví, jak byl předtím vypsán. Sekcím jsem chtěl dát číslovací offset, abych mohl dělat seriály přes sekce.
Každý článek bude mít rodiče - sekci. Projedeš si selectem všechny články GROUP BY parent. Tím získáš počty v nejnižších sekcích. Aktualizuješ. Tak to projdeš až ke kořeni. Není to sice tak pohodlné jako rekurze, ale fungovat to bude.
Na konci článku je dobré vypsat seznam článků v sekci. Přitom se dá zjistit pořadí aktuálního článku (a ten jeden nedělat jako odkaz).
Jsem z toho jelen GROUP BY
jsem nikdy moc nepochopil a nevím, jak udělat, aby to do toho počtu nedávalo
samotné sekce. No je to každopádně hrůza, asi zatím spíchnu nějaký
work-around. Vnoření tolika sekcí do sebe tak, aby to bylo vidět, plánuji
jen na 2 místech, tak to asi zatím zadám manuálně a bude
Na konec článku chci určitě dát nějaký widget, vídal jsem "podobné články", kompletní seznam sekce jsem ještě neviděl. Možná by bylo dobré 3 odkazy: předchozí, další a sekce.
SELECT parent, count(*) AS pocet FROM clanek WHERE NOT je_sekce GROUP BY parent;
Tohle si dáš do pomocné tabulky, podle které aktualizuješ. Pak si podle ní vyhledáš všechny rodiče aktualizovaných záznamů, zase aktualizuješ a tak dál, dokud nebude prázdná. V tom selectu už nebude count(*), ale sum(pocet).
Kompletní seznam článků sekce najdeš třeba na linuxsoft.cz.
Díky, zatím to nějak nahackuji a potom se k tomu vrátím
Zobrazeno 20 zpráv z 20.