Una caratteristica tipica che, come programmatori, ci capiterà di dover implementare è la gestione di un’alberatura di categorie e sottocategorie.
Esistono diversi modi di strutturare il database: quello più comune consiste nello creare una tabella categories, con le colonne id, nome, parent ed eventualmente level. Per poter poi stampare a video il nostro albero, potremo usare o dei cicli annidati che sviluppano due istanze del recordset, oppure un unico ciclo che stampa il risultato di due o più JOIN.
Tuttavia, in entrambe queste soluzioni bisogna sapere a priori quanti livelli di profondità abbiamo: 2 livelli = 2 cicli o 2 JOIN… e così via. Con il metodo che vi sto per presentare, invece, sarà possibile ottenere infiniti livelli di profondità. Come? Con il Nested Set Model.
La logica è semplice: invece di pensare ad un albero con dei sottoalberi, pensiamo ad un insieme con dei sottoinsiemi.
Si passerà da questo:

a questo:

Il primo è facilmente rappresentabile in un database, ma come la mettiamo con il secondo? Abbiamo bisogno di due nuovi campi nella tabella categories: left e right. Immaginiamo di numerare gli estremi sinistro e destro di ogni insieme, come nella figura seguente:

In questo modo possiamo riferirci ad un insieme e ai suoi sottoinsiemi, utilizzando una coppia di numeri. La categoria “Televisions”, ad esempio, sarà 2-9, “Flash” sarà 12-13…
Aggiungendo una nuova categoria (o eliminandone una) bisognerà chiaramente aggiornare gli indici anche delle altre. Un piccolo svantaggio che porta infiniti vantaggi.
La tabella sarà quindi così strutturata:
+-------------+----------------------+-----+-----+ | category_id | name | lft | rgt | +-------------+----------------------+-----+-----+ | 1 | ELECTRONICS | 1 | 20 | | 2 | TELEVISIONS | 2 | 9 | | 3 | TUBE | 3 | 4 | | 4 | LCD | 5 | 6 | | 5 | PLASMA | 7 | 8 | | 6 | PORTABLE ELECTRONICS | 10 | 19 | | 7 | MP3 PLAYERS | 11 | 14 | | 8 | FLASH | 12 | 13 | | 9 | CD PLAYERS | 15 | 16 | | 10 | 2 WAY RADIOS | 17 | 18 | +-------------+----------------------+-----+-----+
Vi ricordo che left e right sono parole riservate in SQL. Pertanto useremo lft e rgt.
Per selezionare l’intero albero delle categorie, non dovremo fare altro che eseguire questa query:
1 2 3 4 5 6 | SELECT node.name FROM nested_category AS node, nested_category AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt AND parent.name = 'ELECTRONICS' ORDER BY node.lft; |
Grazie a questo sistema, potremo ricavare un albero di infiniti livelli, senza doverne sapere a priori il numero! Geniale, no?
Vi rimando alla pagina inglese da cui ho tratto questo post e che spiega in modo più dettagliato come eseguire tutte le query necessarie alla gestione: inserimento, modifica, eliminazione e visualizzazione delle categorie.




Non e’ piu pratico il caro vecchio sistema con parentid ?
Id, category, parentid
Con una bella procedure ricorsiva si percorre l’albero e nn vi sono problemi di manutenzione
Roberto
i problemi sorgono con la modifica e la cancellazione dei record
Sì, nel caso in cui ci siano tante categorie, questo metodo non è consigliato, perchè bisogna aggiornare fin troppi record.
i problemi sorgono dopo però
Davvero ottimo lavoro ! Thank for share !