Autor Zpráva
Jcas
Profil *
Toto je těžké. Jak to říct a jak zvolit správný nadpis.

Znáte situaci, že máte mnoho checkboxů a uživatel si může zaštkrtnou několik z nich. Jeden i více a v různých kombinacích. Taková situace, kdy stanovuji, do kterých kategorií příspěvěk patří.

Příkl. Máme checkboxy "dům, zahrada, les, město, zvěř, rostliny, krmivo, nemoci atd."
Když bude chtít uživatel psát o nemocech srnek, tak jeho příspěvek bude patřit do: les, svěř, nemoci.

Takže máme velkou množinu prvků(checkboxů)(a bude se časem zvětšovat), kdy uživatel má možnost zvolit jakoukoliv kombinaci prvků a jakékoliv množství prvků z určité množiny.

A jak to nyní zpracovat? Připadá mi nesmysl na každou kategorii zakládat sloupec v SQL a při následném výpisu kontrolovat zda je v každém sloupci true, nebo false.

Brácha mi poradil dvojkovou soustavu. To vypadá šikovně, ale moc nevím jak na to.
Jeden sloupec v SQL, kam se uloží binární číslo a dle toho bych poznal co uživatel zvolil.

Moje představa: budu např. 10-ti ciferné číslo. 0000000000
Uživatel zaškrtne 5. a 8 checkbox, tak bych číslo upravil na 0000100100
A při výběru dat bych musel nějak udělat obrácený postup.

Je to nesmysl, nebo by to takhle nějak šlo? Jak se to dělá?

Mockrát děkuji
juriad
Profil
Denormalizace!
tabulka příspěvky (id, titulek, autor, text)
tabulka kategorie (id, název)
tabulka příspěvek_v_kategorii (příspěvek_id, kategorie_id)

Potřebuješ ještě třetí tabulku, která bude pro každý článek mít tolik řádků, v kolika je kategoriích.

Některé časteji řešené dotazy pro MySQL - FAQ
Jcas
Profil *
Bezva děkuju. Vlastně je to docela jednoduché, akorát mi připadalo zbytečné na tak jednoduchou věc dělat více tabulek.

Noční můra se naplnila. Skládat SQL dotaz na propojení několika tabulek. :))
martin1312
Profil
Obecne zobraté, čím viac tabuliek na riešenie prepojení, tým jednoduchšie sa s nimi pracuje (samozrejme netreba brať krajné situácie).
Ak ti nebude jasný nejaký SQL select, tak napíš a určite ti niekto poradí :)
juriad
Profil
Noční můra by byla v původním schématu přidat novou kategorii a vypsat všechny články v nějaké kategorii.
Proti tomu jsou jeden, dva joiny úplná pohádka. Pokud si navíc napíšeš nějakou databázovou abstrakci na straně PHP, tak všechny selecty budeš provádět přehledně na jediném místě.
Jcas
Profil *
Tak jsem si udělal takovou strukturu, jak by byli jednotlivé kategorie a pod kategorie.
To jsem si udělal pro přehlednost i pro stavbu <form>. Pro přehlednost jsem si i duplikoval stejné možnosti pro jinou kategorii. Proto mám stejná slova napsána 10*
Je to takový pavouk, co se větví a stejně tak se budou větvit i další oblasti krom toho chovu.
ukázka(pdf)

Znamená to, že?
Do tabulky kategorie - to prostě nastrkám jak to běží a leží(i podkategorie), takže např krmení tam bude jednou jedinkrát s jedinečným id.
Jak potom poznám co k čemu patří?

A v tabulka příspěvek_v_kategorii, bude pro příspěvek 5 řádků?
ps. to číslo je nyní pouze pořadové - počet řádků.
1. - Dotazy ohledně chovu
2. - chov zvířat
3. - králíci
4. - chov
5. - krmení

Pochopil jsem to správně? Ale to ta třetí tabulka bude mít naprosto nehorázné množství řádků.

-ta stavba by měla být taková, abych "do té tabulky co jsem si udělal pro přehlednost" mohl kdykoliv přidat jak řádek, tak sloupec(pod-pod-kategorie)
-a uživatel by měl mít možnost skončit dřív ve specifikaci, tedy nemusel by se při zaklikávání checkboxů vždy pro klikat až nakonec. (Kdyby třeba nevěděl, kam dotaz zařadit, tak by skončil u "králík" a dál by to nespecifikoval
juriad
Profil
Navrhl bych to jinak, z prvního příspěvku nebylo jasné, že kategorie tvoří hierarchii.


Doplněno:
Mimochodem, bavíme se o kategorizaci článků, které budeš psát ty, nebo o fóru, kde si budou radit chovatelé navzájem?
On je v tom dost velký rozdíl; zbytek tohoto příspěvku popisuji strukturu fóra.


Napřed se zamysli, jestli opravdu chceš tak hluboké kategorizování (4 úrovně), nešlo by to omezit? Přijde mi to z pohledu uživatele nepřínosné, bude pořád klikat hlouběji a hlouběji. Podívej se, jak to funguje zde na Diskusi, kategorie sice jsou, ale příliš na nich nezáleží. Pokud někoho zaujme téma a umí poradit, odpoví; pokud mu budeš házet klacky pod nohy v podobě mnoha kategorií, nebude ho bavit je pořád všechny prolézat.

Schéma:
kategorie (názve_kategorie, id, rodičovská_kategorie, část_kategorie, pořadí_kategorie)
příspěvky (id, kategorie_id, titulek, autor, text)

Pokud si omezíš počet úrovní, zjednoduší se ti dotazy do databáze a nemusíš používat šílenosti typu traverzování kolem stromu. Pokud budeš mít jednu 1–2 úrovně, vystačíš si s uvedeným schématem. Pro víc úrovní bys potřeboval rychle určit jestli je kategorie podkategorií jiné kategorie.

Já bych to viděl na 2 úrovně, maximálně:
(názve, id, rodič_id, část, pořadí)
Chov králíků 1,NULL,1,1
- chov 2,1,1,1
- posuzování 3,1,1,2
- zdraví 4,1,1,3
Chov drůbeže 5,NULL,1,2
- chov 6,5,1,1
- posuzování 7,5,1,2
- zdraví 8,5,1,3
Chov holubů 9,NULL,1,3
- chov 10,9,1,1
- posuzování 11,9,1,2
- zdraví 12,9,1,3
Chov ovcí 13,NULL,1,4
- chov 14,…
- posuzování 15,…
- zdraví 16,…
Chov koz 17,NULL,1,5
- chov 18,…
- posuzování 19,…
- zdraví 20,…
Chov jiných zvířat 21,NULL,1,6
- chov 22,21,1,1
- posuzování 23,…
- zdraví 24,…
------ grafický oddělovač na seznamu kategorií ------
Činnost organizace 25,NULL,2,1
------ grafický oddělovač na seznamu kategorií ------
Akce a výstavy 26,NULL,3,1

Příspěvek bude patřit do právě jedné kategorie, té nejhlubší; SQL dotaz se pak postará o zbytek.
Než vybírat kategorii checkboxy, bývá lepší vlézt do kategorie a tam vytvářet dotaz, výběr zařazení provedl tazatel nenuceně sám zatímco vstoupil do kategorie.

Kategorie budeš řadit primárně podle sloupce část_kategorie, sekundárně podle pořadí_kategorie; kdykoli se zvýší část, vykreslíš oddělovač.
Na pořadí ID vůbec nezáleží, takže klidně můžeš později vytvořit kategorii ("draní peří",102,5,2,1).
Jcas
Profil *
Nevím, jestli to zvládnu srazit. Klasické diskuzní forum to nebude. Špatné zkušenosti se spamem a zadrbávání fora nesmysly(samo-zabezpečení proti spamu není hlavní důvod).
Nechceme polemiku a mnohačetnou diskusi. Ani není k dispozici moderátor fora.

Dotazy se budou rozesílat emailem na patřičnou osobu=specialistu. Jenom co se týče zdravotních problému, tak máme už teď 3 veterynáře. Jednoho na králíky, jednoho na holuby a jednoho na drůbež.

Ale když se dívám na ten tvůj návrh, tak se to skoro začíná podobat tomu mému začátku, když jsem chtěl vracení 1,0.
A takhle jak to máš by to zvládlo i tři úrovně? Na ty bych to asi stáhnul určitě.

-jedna věc je:uživatel podá dotaz a odpověď zpracuje specialista pro danou problematiku
-za druhé: způsob uložení
-za třetí: zobrazení a případná selekce zobrazení
juriad
Profil
Aha, už je mi to jasnější.
Kategorie tvoří stromovou strukturu.
A
- AA
- - AAA
- - AAB
- AB
- - ABA
- - ABB
B
- BA
…
Příspěvek bude patřit vždy do jedné jediné kategorie.
Pokud je příspěvek v kategorii AAA, měl by být zobrazovaný i v kategorii AA a kategorii A; nikdy se nestane, že by měl být i B či AB.

Pokud je tomu tak, je na čase zvolit vhodnou reprezentaci stromu kategorií.
Pokud se použije id rodiče kategorie přímo v kategorii, tak je to omezené na několik málo úrovní; selecty se s každou další úrovní zesložití.
Traverzování kolem stromu mi přijde jako moc velké kladivo a nepěkně se mi s tím pracuje.
Navrhuji použít následující strukturu:
kategorie (id, název, úroveň)
kategorie_v_kategorii (id_rodiče, id_potomka)
příspěvky (id, kategorie, titulek, autor, text)

kategorie_v_kategorii obsahuje všechny relace (bude jich hodně, ale pár desítek záznamů nám nevadí):
AA je v A, AAA je v A, AAB je v A, AB je v A, ABA je v A, ABB je v A, AAA je v AA, AAB je v AA, ABA je v AB, ABB je v ABB, a dokonce obsahuje i sama sebe: A je v A, AA je v AA, AAA je v AAA, AAB je v AAB, AB je v AB, ABA je v ABA, ABB je ABB

Dotaz na příspěvky, které jsou v A nebo v podkategoriích by vypadal:
SELECT p.* FROM prispevky p # zajímají nás příspěvky
JOIN kategorie k ON p.kategorie = k.id # které jsou v kategoriích
JOIN kategorie_v_kategorii k2 ON k2.id_potomka = k.id # které jsou uvnitř kategorie (kategorie je uvnitř sama sebe; zobrazí tedy i příspěvky z A)
WHERE k2.id_rodice = 1 # která má ID 1 (to bude ta kategorie A) 
Jcas
Profil *
Tohle vypadá dobře. To bude přesně to pravé.
Tedy pokud uživatel vytvoří dotaz v kategorii ABC, tak:
-dynamické plnění, abych nemusel předem definovat všechny možnosti.

kategorie
1. Zkontroluji existenci kategorie (id, A, 1)
Stejně tak (id, B, 2) a (id, C, 3)
2. Pokud neexistuje - vložím do db.

kategorie_v_kategorii
Zde budou muset být záznamy pro:
(id_A, id_B), (id_A, id_C), (id_B, id_C)
3. zkontroluji jejich existenci - případně vložím.

kategorie (uroven) - by my měla prozradit počet u kolika záznamů musím kontrolovat existenci - případně kolik záznamů musím vložit.

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

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

0