BigThink

Gestire infiniti livelli di categorie in SQL

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.

Articolo scritto da Ghido

Fondatore di BigThink.it, si occupa dello sviluppo e del coordinamento dei progetti tecnologici. Specializzato nel Marketing su Facebook e nello sviluppo di Applicazioni Social, fa consulenza e formazione ad aziende ed agenzie.

Leggi anche...

Il web sotto attacco con SQL injection!

Il web sotto attacco con SQL injection!

Nell'ultima settimana, oltre un milione di siti sono stati attaccati da un bot che ha iniettato nei loro database un codice maligno che infetta i computer degli utenti che visitano i siti in questione. Un attacco massiccio: se cercate su Google le stringhe www.nihaorr1.com/1.js, www.adw95.com/b.js o www.banner82.com/b.js, troverete centinaia di migliaia di siti ...

5 Commenti

  1. 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

    7 novembre 2011, 02:48
  2. i problemi sorgono con la modifica e la cancellazione dei record :D

    8 ottobre 2010, 01:10
    • Sì, nel caso in cui ci siano tante categorie, questo metodo non è consigliato, perchè bisogna aggiornare fin troppi record.

      11 ottobre 2010, 18:00
  3. i problemi sorgono dopo però :D

    8 ottobre 2010, 01:10
  4. Davvero ottimo lavoro ! Thank for share !

    17 agosto 2010, 15:48

3 Citazioni