Autor | Zpráva | ||
---|---|---|---|
fm_pr Profil * |
#1 · Zasláno: 29. 6. 2015, 17:01:34
Zdravím,
mějme pro jednoduchost jednu jedinou tabulku kategorie a u ní jsou v jednom sloupci i vypsané počty produktu v ní: id parent_id count_articles - v tomto sloupci je pro jednoduchost už předpřipraven počet produktu v této kategorii PRIKLAD tabulky: 1;NULL;0 2;1,1 3;1;3 4;2;10 5;2;5 graf pro tabulku viz. výše vypadá takto: KATEGORIE1 (obsahuje 0 clanku) -KATEGORIE2 (obsahuje 1 článek) --KATEGORIE4 (obsahuje 10 článků) --KATEGORIE5 (obsahuje 5 článků) -KATEGORIE3 (obsahuje 3 články) snažím se nyní vymyslet MySQL dotaz (ne kód v php!), který mě vrátí kategorii a počet článků VČETNE počtu článků v jejím podstromu, tedy pro příklad výše by měl být výsledek: 1;19 2;16 3;3 4;10 5;5 Prosím nepište rady typu předělej celou databázi nebo to naprogramuj v php pomocí rekurze ;) Jinak nemusí to být časově nijak extra optimalizovaný, může to být klidně nějaká procedura s rekurzí atd... ale musí to vyplyvnout tu tabulku... vítěz má flašku ;) |
||
tiso Profil |
#2 · Zasláno: 29. 6. 2015, 21:05:39
problém takto uloženého stromu kategórií je ten, že musíš vedieť hĺbku vnorenia. Pre tvoj prípad:
SELECT lvl1.id, lvl1.count_articles + IFNULL(SUM(DISTINCT lvl2.count_articles), 0) + IFNULL(SUM(DISTINCT lvl3.count_articles), 0) count FROM categories lvl1 LEFT JOIN categories lvl2 ON lvl1.id = lvl2.parent_id LEFT JOIN categories lvl3 ON lvl2.id = lvl3.parent_id GROUP BY lvl1.id; |
||
fm_pr Profil * |
#3 · Zasláno: 29. 6. 2015, 22:40:06
tiso:
v tom je právě problém, hloubka vnoreni je obecne n... neni to zadna legrace toto vyresit a ani na zahranicnich forech nikdo nenabizi zadne funkci reseni... vsichni odkazuji na rekurze a klazuli WITH, coz v mysql neni implementovany... dneska jdu touto cestou: 1) nacist si pocty clanku do jednotlivych kategorii (to je primitivni a v mem zadani uz je tento krok preskocen) 2) projit kurzorem vsechny listy stromu kategorii a postupne dalsim kurzorem pro kazdy uzel na ceste od kazdeho listu stromu k jeho vrcholu pricitat aktualni pocet clanku no neni to zadna legrace a to jsem veril, ze uloha "vrat pocty clanu v kategoriich vcetne jejich podkategoii" neni nijak slozita a davno vyresena... no kdyby mel nekdo univerzalni reseni, sem s nim :) |
||
Kajman Profil |
fm_pr:
„kdyby mel nekdo univerzalni reseni, sem s nim“ Přejít na databázi, která rekurzivní dotazy podporuje. Určitě to půjde v postgresql nebo oracle. Ukázka pro oracle SELECT id, SUM(count_articles) count_articles FROM (SELECT connect_by_root id id, count_articles FROM kategorie CONNECT BY NOCYCLE PRIOR id = parent_id) GROUP BY id ORDER BY id Ukázka pro postgresql WITH RECURSIVE s AS ( SELECT k.id, k.parent_id, k.count_articles, k.id gid FROM kategorie k UNION SELECT ks.id id, s.parent_id, ks.count_articles, s.gid FROM kategorie ks JOIN s ON ks.parent_id=s.id ) SELECT gid id, SUM(count_articles) count_articles FROM s GROUP BY gid ORDER BY gid V mysql si můžete leda pomoci pomocnými sloupci pro traverzování kolem stromu, pak by to jít mělo nějak takto SELECT k.id, Sum(s.count_articles) count_articles FROM kategorie k JOIN kategorie s ON k.lft <= s.lft AND k.rgt >= s.rgt GROUP BY k.id ORDER BY k.id |
||
Časová prodleva: 3 dny
|
|||
fm_pr Profil * |
#5 · Zasláno: 2. 7. 2015, 19:44:49
tak po dvou třech dnech jsem přidal lft a rgt a v kombinaci s původním parent_id je to celkem mocný nástroj (parent_id vše krásně jistí, kdyby se náhodou lft a rgt nějak rozsypalo). Bohužel jsem přišel na velmi nepříjmenou drobnost - jeden článek mohu mít zařazen do více kategorií. S tím jsem v zadání nepořítal a pokud jsem psal, že KATEGORIE4 obsahuje 10 a KATEGORIE5 obsahuje 5 článků, úplně jsem zapomněl na tom, že tabulka články kategorie je M:N, takže jeden článek je ve více kategoriích, takže v kategorii 4 a 5 rlzných článků, těch různých článků může být třeba jen šest (respektivě minimálně 5)
máte nápad jak to do funkčního kódu zapracovat? SELECT k.id, k.name, Sum(s.count_articles) count_articles FROM _is_categories k JOIN _is_categories s ON k.lft <= s.rgt AND k.rgt >= s.rgt GROUP BY k.id ORDER BY k.id Tedy jak získat s.count_articles z tabulky např. articles_categories ? |
||
Kajman Profil |
#6 · Zasláno: 2. 7. 2015, 20:39:45
Pokud tedy opravdu nevadí, že to bude pomalejší, tak bych zkusil
SELECT k.id, k.name, Count(DISTINCT ac.article_id) count_articles FROM _is_categories k JOIN _is_categories s ON k.lft <= s.rgt AND k.rgt >= s.rgt LEFT JOIN articles_categories ac ON s.id = ac.category_id GROUP BY k.id ORDER BY k.id „lft a rgt a v kombinaci s původním parent_id je to celkem mocný nástroj“ Ještě se občas přidává předpočítaný level nebo hloubka zanoření. |
||
fm_pr Profil * |
#7 · Zasláno: 2. 7. 2015, 21:13:55
perfektní, skutečně to funguje... :)
ještě bych potřeboval jen přidat podmínku articles.active=1 (nyní se započítají počty všech článků v kategoriich, potřebuju omezit na jen aktivní články) a pokud pošlete adresu na fantommax zavinac seznam.cz , tak máte slíbenou flašku dle výběru :) nebo paypal ucet... ;) |
||
Kajman Profil |
SELECT k.id, k.name, Count(DISTINCT a.id) count_articles FROM _is_categories k JOIN _is_categories s ON k.lft <= s.rgt AND k.rgt >= s.rgt LEFT JOIN articles_categories ac ON s.id = ac.category_id LEFT JOIN articles a ON ac.article_id = a.id AND a.active = 1 GROUP BY k.id, k.name ORDER BY k.id |
||
Časová prodleva: 10 let
|
0