Diskuze: Nekonečný počet podkategorii
V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.


Zobrazeno 10 zpráv z 10.
K personalizaci obsahu a reklam, poskytování funkcí sociálních médií a analýze naší návštěvnosti využíváme soubory cookie. Informace o tom, jak náš web používáte, sdílíme se svými partnery pro sociální média, inzerci a analýzy. Partneři tyto údaje mohou zkombinovat s dalšími informacemi, které jste jim poskytli nebo které získali v důsledku toho, že používáte jejich služby.
Používáme nezbytné cookies pro fungování webu a s tvým souhlasem také analytické a marketingové cookies.
Zajišťují základní funkce, bezpečnost a služby, které sis vyžádal. Nelze je vypnout.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| ITnetwork | ITnetwork | Provoz webu, relace, přihlášení a uložení nastavení cookies. | PHPSESSID, auth_token, sid, itn_consent_impression, __Host-itn_consent | Relace až 1 rok |
| Google Tag Manager | Správa značek a načítání měřicích nástrojů webu. | Žádné | Neukládá se | |
| Google Fonts | Načítání typografie webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google Hosted Libraries | Načítání potřebných knihoven a stylů webu. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele | |
| Google reCAPTCHA | Ochrana formulářů a webu před zneužitím. | _GRECAPTCHA, rc::a, rc::b, rc::c, rc::f | Relace až 180 dní | |
| YouTube | Přehrávání vloženého video obsahu. | localStorage, IndexedDB; cookies after playback interaction | Relace až trvalé úložiště | |
| Vimeo | Vimeo | Přehrávání vloženého video obsahu. | __cf_bm, _cfuvid, vuid, localStorage, IndexedDB | Relace až 2 roky |
| Facebook Login | Meta | Přihlášení pomocí účtu třetí strany. | Úložiště řízené poskytovatelem | Relace až 1 rok |
| GoPay | GoPay | Zpracování uživatelem vyžádané platby. | Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
Pomáhají nám porozumět používání webu a zlepšovat ho.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Analytics 4 | Měření návštěvnosti a používání webu. | _ga, _ga_* | Až 2 roky | |
| Microsoft Clarity | Microsoft | Měření návštěvnosti a používání webu. | _clck, _clsk, _cltk | Relace až 1 rok |
Slouží k měření kampaní, personalizaci reklamy a marketingové komunikaci.
| Služba | Poskytovatel | Účel | Cookies a úložiště | Doba uložení |
|---|---|---|---|---|
| Google Ads | Měření kampaní, reklama a remarketing. | _gcl_au, _gcl_ls | Relace až 90 dní | |
| Meta Pixel | Meta | Měření kampaní, reklama a remarketing. | _fbp, _fbc, localStorage | Až 90 dní |
| Sklik | Seznam.cz | Měření kampaní, reklama a remarketing. | retargeting, sid, szn:* | Relace až trvalé úložiště |
| LinkedIn Insight | Měření kampaní, reklama a remarketing. | bcookie, li_gc, lidc, __cf_bm | Relace až 1 rok | |
| Ecomail | Ecomail.cz | Měření kampaní, reklama a remarketing. | ecmid, Úložiště řízené poskytovatelem | Dle podmínek poskytovatele |
| Atribuce kampaní ITnetwork | ITnetwork | Přiřazení návštěvy a objednávky ke kampani. | campaign_clid[*], user_session_context | Až 1 rok |
V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.


Můžeš to vyřešit tak, že všechny kategorie (i podkategorie) dáš do jedné tabulky a poté akorát vytvoříš tabulku vztahů:
| Název nadřazené kategorie | Název podkategorie |
| kategorie1 | podkategorie1 |
| podkategorie1 | podkategorie2 |
| podkategorie2 | podkategorie3 |
Pokud bys to řešil na Oracle, dá se to vyřešit celkem pohodlně pomocí
jedné tabulky a funkce LISTAGG.
Tabulka by obsahovala následující:
| nazev_kategorie | id_podkategorie | nazev_podkategorie |
| kategorie1 | 1 | podkategorie1 |
| kategorie1 | 2 | podkategorie2 |
| kategorie1 | 3 | podkategorie3 |
| kategorie2 | 1 | podkategorie1 |
| kategorie2 | 2 | podkategorie2 |
Sloupec id_podkategorie je tu pouze pro potřeby řazení ve funkci, abys měl na výstupu kategorie správně seřazené.
Funkce by pak vypadala následovně:
SELECT LISTAGG(nazev_podkategorie, '/') WITHIN GROUP (ORDER BY id_podkategorie)
FROM tabulka_kategorii
WHERE nazev_kategorie = 'kategorie1';
Pokud to děláš na MS SQL, tak něco podobného funguje tuším od verze
2017.
V dřívějších verzích se na to musí jít trochu oklikou, ale taky se to
dá udělat.
Na jiných databázích jsem to nikdy neřešil, ale určitě to taky půjde

Hledal jsem po netu a nasel tohle. Vypada to, ze je to to co potrebuji(pokud teda nenarazim na neco co mi tahle moznost zneprijemni praci)
CREATE TABLE Category (
id INT AUTO_INCREMENT NOT NULL,
parent_id INT DEFAULT NULL,
PRIMARY KEY(id)
) ENGINE = InnoDB;
ALTER TABLE Category ADD FOREIGN KEY (parent_id) REFERENCES Category(id);
Vytvori se kategorie bez parent_id, potom podkategorie s parent_id a podle
toho se tahaji podaktegorie atd..
Uvidime.
No tak se to dá udělat, ale myslím že jen v případě, kdy budeš mít
pro všehcny kategorie vždy stejný počet podkategorií. Jak víš kolikrát
na sebe máš joinovat tu tabulku?
Musel by sis někde v proměnné uchovávat počet podkategorií a podle toho
pak generovat dynamické SQL.
Nebo sem zkus napsat ten join, jak jsi to myslel.
sloupce: id, parent_id, name ...........
pak můžeš využít něco takového
WITH category_tree AS
(
SELECT *, 0 AS category_level
FROM dbo.category
UNION ALL
SELECT c.*, category_level + 1 as category_level
FROM category_tree ct
JOIN dbo.category AS c
ON c.Id = ct.parent_id
)
SELECT *
FROM category_tree
Myslím, že tohle nebude fungovat.
V definici category_tree selectuješ z category_tree.
Myslím, že tohle nebude fungovat.
V definici category_tree selectuješ z category_tree.
V tom problém není - jedná se o tzv. Recursive CTE - viz např. https://technet.microsoft.com/…ql.105).aspx
Je to nástroj po práci s hierarchickými daty v MS SQL.
Ale tak, jak je to v příspěvku výše uvedeno to fungovat nebude, protože
jednak jsou tam chyby a především tím nezíská to co je požadováno v
zadání - veškeré podkategorie dané kategorie.
Bylo by to nějak takto:
WITH category_tree AS
(
SELECT *, category_level = 0, id AS root_id
FROM category
WERE parent_id IS NULL -- touto podminkou vyberu nejvyssi uroven, ktera nema parenta
UNION ALL
SELECT c.*, category_level = ct.category_level + 1, ct.root_id
FROM category AS c
INNER JOIN category_tree AS ct ON ct.id = c.parent_id
)
SELECT *
FROM category_tree
WHERE root_id = @id -- @id predstavuje id pozadovane kategorie
K tomu se pouziva neco cemu se rika Traverzovani kolem stromu. Funguje to tak, ze mas polozku, ktera ma v sve ID (neni to cislo zaznamu) a pak dva sloupce od a do. Kdyz vytvoris podpolozku, priradis ji cislo ID o jedno vetsi nez je ID polozky a vsechny ID co jsou pod nim zvednes o jedno. Vcetne zaznamu od a do. Vytvori se tak struktura, ktera se pouziva u diskusnich for se zanorenymi komentari. Jednou se mi podarilo ji skutecne rozebehnout, ale blbe se v tom listuje. A k pochopeni je to taky vorech vorechovic. Pekne a spravneji nez ja to u sebe popisuje Jakub Vrana. Ale nechces li si zivot komplikovat moc, jdi prostsi cestou. Treba vetsim poctem tabulek, kde bude mit kazda uroven svou. A pocitam, ze dale nez do 10 zanoreni se nedostanes. Budes mit pak 10 tabulek, kde v kazde vyssi bude odkaz na rodice. Jestli nebudes mit milion podkategorii, pak by to slo dat i do jedne tabulky, kde budes mit sloupec kategorie a sloupec urovne zanoreni a sloupec rodice.
Ahoj, ja by som to riesil kombinaciou uz spomenutych rieseni. Nie je to uplne programatorsky spravne, ale podla mna jednoduche riesenie tvojho problemu. Nemam moc rad zlozite sql
1. vytvor si tabulku, ako pises, kam sa budu ukladat vsetky zaznamy
CREATE TABLE Category (
id INT AUTO_INCREMENT NOT NULL,
name VARCHAR(50),
parent_id VARCHAR(60),
PRIMARY KEY(id)
) ENGINE = InnoDB;
velkost VARCHAR potom bude zavisiet podla toho, kolko bude zaznamov v tabulke, a kolko budes pocet podkategorii (bude to treba hlidat, aby nedoslo k preteceniu).
Pri pridavani musis vediet parent_id, a preto by som si ukladal do parent_id rovno celu strukturu. Vyhnes sa tak zlozitym repeatom v sql. Ako to myslim:
| id | name | parent_id |
| 1 | domena.cz | NULL |
| 2 | kat-1 | 1 |
| 3 | podkat-1 | 1-2 |
| 4 | kat2 | 1 |
| 5 | podkat-2 | 1-4 |
| 6 | podpodkat-2 | 1-4-5 |
Pri vytvarani novej (pod)kategorie vies parent_id kde kam zaradis novu kategoriu(domena.cz, alebo nejaka podkategoria). Problem je, ze poznas len parent_id a nevies celu strukturu az k domena.cz. Preto si tu strukturu uloz, sice to zaberie viac miesta, ale na rychlost to az taky vplyv mat nebude.
povedzme ze chces pridat novu podkategoriu, ktorej parent_id = 6 ( bude patrit do podpodkat-2).
$parent_id_str = execMyQuery('Select parent_id from category where id = ' . $parent_id);
$parent_id_str .= "-" .$parent_id;
execMyQuery("INSERT INTO category (id, name, parent_id) VALUES ('','$newCatName','$parent_id_str')");
najprv ziskas parent_id_str z tabulky, to zretazis s id nadkategorie a to potom ulozis ako novy zaznam. execMyQuery je nejaka implicitna funkcia ktora vykona sql query, a vrati ti hodnotu.
ked si budes chciet vytiahnut strukturu:
$result = execMyQuery('Select parent_id from category where id = ' . $category_id);
$result = explode($result, '-');
$condition = "id = '". implode($result, "' OR id ='") . "'";
$categoryTree = execMyQuery("SELECT id, name FROM category WHERE $condition ORDER BY id");
a teraz budes mat v categoryTree pekne v poli v poradi domena.cz , kat-2,
podkat-2, podpodkat-2.
Na rychlost to nema vplyv lebo sa vzdy odkazujes cez primarne kluce, ktore su
indexovane a nepouzivas fulltext vyhladavanie. ako oddelovac mozes pouzit
cokolvek, pomolcku, podtrznik, pismenko, zvislitko, ...
je treba osetrit to retazenie pre kategoriu priamo pod domena.cz, a mnoho dalsich drobnosti
Berte to ako myslienku. Je to pisane z hlavy, tak to berte s rezervou.
Zobrazeno 10 zpráv z 10.