Nell'ipotesi di solo due livelli, categoria padre e categorie figlie, volendo ridurre i tempi di esecuzione dovuti alle troppe query (anche solo 50 categorie principali implicherebbero 51 query, il che è tutt'altro che ottimale per una pagina), credo la cosa si possa fare con una sola query e qualche accorgimento in fase di lettura dei risultati. Ricordiamoci che dove possibile è consigliabile far lavorare un tantino di più il motore SQL una sola volta, piuttosto che fare tante query diverse che introdurrebbero molto overhead.
Semplifico l'esempio per farti capire, poi tu potrai adattarlo alla tua tabella, con i nomi corretti.
Id è l'id della categoria, Pid è l'id del padre, 0 se è categoria principale.
TABELLA:
codice:
id | nome | Pid
1 | padre 1 | 0
2 | padre 2 | 0
3 | figlio di 1-1 | 1
4 | figlio di 2-1 | 2
5 | padre 3 | 0
6 | figlio di 2-2 | 2
7 | figlio di 3-1 | 5
8 | figlio di 1-2 | 1
9 | padre 4 | 0
La query è la seguente:
SELECT tab1.id as IDpadre, tab1.nome as padre, tab2.id as IDfiglio,tab2.nome as figlio from TABELLA as tab1 join TABELLA as tab2 on(tab1.id=tab2.pid or (tab1.pid=0 and tab1.id=tab2.id)) order by IDpadre,IDfiglio;
Il risultato è il seguente:
codice:
IDpadre | padre | IDfiglio | figlio
1 | padre 1 | 1 | padre 1
1 | padre 1 | 3 | figlio di 1-1
1 | padre 1 | 8 | figlio di 1-2
2 | padre 2 | 2 | padre 2
2 | padre 2 | 4 | figlio di 2-1
2 | padre 2 | 6 | figlio di 2-2
5 | padre 3 | 5 | padre 3
5 | padre 3 | 7 | figlio di 3-1
9 | padre 4 | 9 | padre 4
che come vedi, guardando la colonna figlio, è il risultato da te voluto.
Ci sono righe in apparenza ridondanti, dove il padre è associato a se stesso, servono per poter comunque ottenere dalla query le categorie principali che non hanno figli.
Basterà un piccolo controllo in fase di output per gestirlo.
Se non funziona fatemi un fischio.