Che tipo di struttura DB dovrei usare per un sito ha una sottocategoria infinita?
-
07-07-2019 - |
Domanda
Ad esempio, "Dole Banana" è un tipo di prodotto, è elencato nella sezione "Banane" categoria, quando apro la " Frutta " categoria, voglio vedere " Dole Banana " ;.
+ Food
|--+ Fruits
|------+ Bananas
|------+ Apples
|--+ Vegetables
|------+ Onion
|------+ Spinach
Soluzione
Di solito ho usato alberi da sinistra a destra che sono molto ben adattati alle query del database. Hai un parentId, valore sinistro e destro per ciascun nodo. Ogni nodo figlio ha un valore sinistro / destro compreso tra i nodi padre sinistro e destro che rende molto facile trovare, ad esempio, tutti i figli / genitori di un nodo. Dà un leggero sovraccarico sugli inserimenti, ma non dovrebbe avere un grande impatto se non si inserisce molto.
Modifica: solo un avvertimento, è necessario effettuare le operazioni di inserimento / aggiornamento in una transazione bloccata o l'albero può incasinarsi.
Altri suggerimenti
Se stai cercando risorse online che risolvono questo problema, " Archiviazione di un albero in un database " sarebbe una buona frase di ricerca.
Per quanto riguarda la soluzione, si noti che ogni sottocategoria può avere una o zero categorie principali. Pertanto, l'intero albero può essere memorizzato in una singola tabella autoreferenziale con un "genitore" campo.
Utilizzando l'albero di esempio:
ID | PARENT | NAME
-----+--------+-------------
1 | null | Food
2 | 1 | Fruits
3 | 2 | Bananas
4 | 2 | Apples
5 | 1 | Vegetables
6 | 5 | Onion
7 | 5 | Spinach
Una tabella " Categorie " con 3 campi.
- CategoryId non null (chiave primaria)
- ParentCategoryId null
- NomeCategoria non nullo
Per ottenere tutte le categorie principali
select * from Categories where ParentCategoryId is null
Per ottenere tutte le sottocategorie di alcune categorie specifiche:
select * from Categories where ParentCategoryId = 12
È possibile utilizzare una struttura di tabella semplice con parent_category_id e recuperare l'intero albero con ricorsione o implementare i valori sinistra / destra e recuperare l'intero albero utilizzando il metodo di attraversamento dell'albero preordinato.
Se intendi un numero infinito di livelli, allora una tabella autoreferenziale che può essere ripetuta. Esempio: StuffID, StuffName, StuffParentID (da FK a ID roba)
Per un numero finito, tabelle fisse: genitore-figlio-nipote
CREATE TABLE [dbo].[Category](
[CategoryId] [int] NOT NULL,
[ParentCategoryId] [int] NULL,
[CategoryName] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Category] PRIMARY KEY CLUSTERED
(
[CategoryId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON
[PRIMARY]
GO
ALTER TABLE [dbo].[Category] WITH CHECK ADD CONSTRAINT [FK_Category_Category] FOREIGN KEY([ParentCategoryId])
REFERENCES [dbo].[Category] ([CategoryId])
GO
ALTER TABLE [dbo].[Category] CHECK CONSTRAINT [FK_Category_Category]
GO
Per una gerarchia infinita, utilizzare algoritmo di attraversamento dell'albero di preordine modificato
Ecco un approccio diverso che potrebbe esserti utile. Ha costi di manutenzione leggermente superiori rispetto all'approccio PARENT_ID o lft / rght, ma il recupero è molto più semplice (e più veloce).
Le banane Dole possono essere nella tabella dei prodotti. Hai un unico ID_categoria per un prodotto.
Avevamo l'obbligo di consentire più categorie per un prodotto. Questo ci ha portato ad avere una tabella di join categorie_prodotti, dove il prodotto potrebbe avere più righe unite. Quindi, abbiamo dovuto decidere se avere le banane Dole solo nelle banane o anche nelle banane e in tutti i suoi genitori. Poiché la velocità di recupero era fondamentale, abbiamo inserito banane Dole nelle sue categorie e in tutte le loro categorie madri. Esistono tre join di prodotti di categoria per le banane Dole.
Usando questa struttura, restituire tutti gli elementi di qualsiasi categoria è facile e veloce, solo una query. Non è possibile farlo nell'approccio PARENT_ID (a meno che non si codifichino genitori, nonni, ecc.) Aggiungere una categoria è facile. La categorizzazione di un prodotto richiede l'inserimento di più righe nella tabella di join. L'eliminazione e lo spostamento di categorie sono un po 'più complicati.