2012-06-19 17 views
6

Non so se quello che sto chiedendo è anche possibile, ma ecco la mia situazione. Ho una tabella strutturato un po 'come questo:Come scrivere una query MYSQL che restituirà i figli annidati sotto i genitori?

+--------------------------------------------------+ 
| id | parent_id | name | category | .... 
+--------------------------------------------------+ 
| 0 |  -1  | item0 |  1  | 
| 1 |  0  | item1 |  1  | 
| 2 |  0  | item2 |  1  | 
| 3 |  2  | item3 |  1  | 
| 4 |  2  | item4 |  1  | 
| 5 |  -1  | item5 |  1  | 
+--------------------------------------------------+ 

Un parent_id di -1 sarà significa che sia un elemento di "base" senza genitori. Ogni articolo avrà più colonne di informazioni. Ho bisogno di qualche uscita tutte le voci di una categoria annidato come la seguente:

item0 => item1  
     => item2 
      => item3 
      => item4 
item5 

non so se ha senso o no, ma si spera che lo fa!

L'unico modo che posso pensare di fare questo è creare una query per ottenere tutti gli elementi "base" (query per righe con parent_id = -1) quindi scorrere tutte le righe risultanti, interrogando per le righe che hanno parent_id uguale all'ID della riga corrente, quindi ripetere il processo andando sempre più in profondità fino a quando non ci sono più figli per un articolo base.

C'è un modo migliore?

Grazie !!

+8

vorrei andare per 'null' per indicare senza genitori –

+3

Sembra una buona idea. Non so davvero cosa sto facendo ;-) – Nate

+0

Puoi ottenere tutto in una volta e quindi costruire la struttura in php: http://stackoverflow.com/questions/2915748/how-can-i-convert- a-serie-di-genitore-figlio-relazioni-in-a-gerarchico-tre – jeroen

risposta

9

Non è possibile in SQL puro.

SQL è progettato per funzionare con i dati relazionali e senza alberi (dati gerarchici).

È possibile rappresentare l'albero in uno schema SQL, tuttavia non sarà possibile generare un albero come si intende fare.

L'unico modo per fare è ottenere un risultato utilizzabile facendo in modo che tutti si uniscano al livello che stai memorizzando.

Il tuo schema attuale può supportare più livelli, tuttavia sarà molto difficile gestire più di uno o due livelli.

Potreste essere interessati a Nested Set Model o Managing hierarchical data in mysql

Ci sono alcuni attuazione del Set Nested come this one lavorare con Doctrine 2

+0

+1 Picchiami. Ecco un [clone del secondo link] (http://www.vbmysql.com/articles/database-design/managing-hierarchical-data-in-mysql) con una migliore formattazione. Saluti! –

+0

@XavierHolt, grazie Ho aggiornato il collegamento. In realtà stavo cercando il post originale su mysql dev ma non sono riuscito a trovarlo. –

1

Questo non è possibile in puro SQL ed è uno degli aspetti della il modello relazionale che genera più critiche.

ti consiglierei di leggere i link a questo post: SQL "tree-like" query - most parent group

E anche, se l'applicazione si basa troppo su questo, vorrei suggerire di dare un'occhiata ad alcuni database non relazionali che possono rappresentare questo tipo di dati in modo migliore, come MongoDB (www.mongodb.org)

1

Spero di aver capito bene la tua domanda (è piuttosto tardi qui e sono appena tornato da un bar), se non lo fossi, basta correggere io e io riscriverò la mia risposta.

Dallo scenario dato, immagino ci sia un altro tavolo genitore, no?

Immaginiamo che gli attributi siano id e nome. Il tavolo per bambini è il dato da te (senza attributi non necessari).

mysql> insert into parent(name) values ('petr'),('tomas'),('richard'); 


mysql> insert into children(name,parent_id) values('michal',1),('tomas',1),('michal'); 


mysql> select parent.id,parent.name,children.name from parent left join children on parent.id = children.parent_id; 

+----+---------+--------+ 
| id | name | name | 
+----+---------+--------+ 
| 1 | petr | michal | 
| 1 | petr | tomas | 
| 2 | tomas | NULL | 
| 3 | richard | michal | 
+----+---------+--------+ 

Per fare questo più volte (genitore ottenuto bambino che ha avuto un figlio che ha avuto un figlio ecc.) È possibile farlo utilizzando più join.

mysql> select parent.id,parent.name as Parent,children.name as Child,children2.name as Child2 from parent left join children on parent.id = children.parent_id left join children2 on children.id = children2.parent_id; 
+----+---------+--------+--------+ 
| id | Parent | Child | Child2 | 
+----+---------+--------+--------+ 
| 1 | petr | michal | NULL | 
| 1 | petr | tomas | dan | 
| 1 | petr | tomas | pavel | 
| 2 | tomas | NULL | NULL | 
| 3 | richard | michal | michal | 
+----+---------+--------+--------+ 

Se i due non rispose quello che hai chiesto o avete bisogno di ulteriori spiegazioni fatemi sapere;]

saluti,

Releis

Problemi correlati