Obvykle existují tři druhy dotazů v hierarchiích, které způsobují potíže:
- Vraťte všechny předky
- Vrátit všechny potomky
- Vrátit všechny potomky (bezprostřední potomci).
Zde je malá tabulka, která ukazuje výkon různých metod v MySQL
:
Ancestors Descendants Children Maintainability InnoDB
Adjacency list Good Decent Excellent Easy Yes
Nested sets (classic) Poor Excellent Poor/Excellent Very hard Yes
Nested sets (spatial) Excellent Very good Poor/Excellent Very hard No
Materialized path Excellent Very good Poor/Excellent Hard Yes
V children
, poor/excellent
znamená, že odpověď závisí na tom, zda mícháte metodu se seznamem sousedství, tj. E. uložení parentID
v každém záznamu.
Pro svůj úkol potřebujete všechny tři dotazy:
- Všichni předkové ukázat věc Země / Spojeného království / Devonu
- Všem dětem se zobrazí „Destinace v Evropě“ (položky)
- Všichni potomci pro zobrazení "Destinace v Evropě" (počet)
Šel bych po zhmotnělých cestách, protože tento druh hierarchie se mění jen zřídka (pouze v případě války, povstání atd.).
Vytvořte sloupec varchar s názvem path
, indexujte jej a naplňte jej hodnotou takto:
1:234:6345:45454:
kde čísla jsou primární klíče příslušných rodičů ve správném pořadí (1
pro Evropu, 234
pro Velkou Británii atd.)
Budete také potřebovat tabulku nazvanou levels
zachovat čísla od 1
až 20
(nebo jakoukoli maximální úroveň vnoření, kterou chcete).
Chcete-li vybrat všechny předky:
SELECT pa.*
FROM places p
JOIN levels l
ON SUBSTRING_INDEX(p.path, ':', l.level) <> p.path
JOIN places pa
ON pa.path = CONCAT(SUBSTRING_INDEX(p.path, ':', l.level), ':')
WHERE p.id = @id_of_place_in_devon
Chcete-li vybrat všechny děti a počty míst v nich:
SELECT pc.*, COUNT(pp.id)
FROM places p
JOIN places pc
ON pc.parentId = p.id
JOIN places pp
ON pp.path BETWEEN pc.path AND CONCAT(pc.path, ':')
AND pp.id NOT IN
(
SELECT parentId
FROM places
)
WHERE p.id = @id_of_europe
GROUP BY
pc.id