2012-06-19 19 views
6

No sé si lo que estoy preguntando es posible, pero esta es mi situación. Tengo una tabla estructurada algo como esto:Cómo escribir una consulta MYSQL que devolverá los elementos secundarios anidados a los padres?

+--------------------------------------------------+ 
| 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 de -1 significa que sea un elemento de "base" con ninguno de los padres. Cada elemento tendrá más columnas de información. Necesito alguna manera de salida todos los elementos de una categoría anidada como la siguiente:

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

no sé si eso tiene sentido o no, pero espero que lo hace!

La única forma en que puedo pensar es hacer una consulta para obtener todos los elementos "base" (consultar filas con parent_id = -1) y luego recorrer cada fila resultante, buscando filas que tengan parent_id igual a la identificación de la fila actual, luego repita el proceso profundizando más y más hasta que no haya más niños para un elemento base.

¿Hay una manera mejor?

Gracias!

+8

Yo iría por 'null' para indicar sin padres –

+3

Eso suena como una buena idea. Realmente no sé lo que estoy haciendo ;-) – Nate

+0

Puede obtener todo de una vez y luego construir la estructura en php: http://stackoverflow.com/questions/2915748/how-can-i-convert- a-series-de-parent-child-relationships-into-a-hierarchical-tre – jeroen

Respuesta

9

No es posible en SQL puro.

SQL está diseñado para trabajar con árboles de datos relacionales no (datos jerárquicos).

Puede representar un árbol en un esquema de SQL, sin embargo, no podrá generar un árbol como pretende hacer.

La única manera de hacerlo es obtener un resultado utilizable haciendo que tantos se unan como el nivel que está almacenando.

Su esquema actual puede admitir varios niveles, sin embargo, será muy difícil administrar más de uno o dos niveles.

Usted puede estar interesado en Nested Set Model o Managing hierarchical data in mysql

Hay alguna aplicación de la conjuntos anidados como this one trabajar con Doctrina 2

+0

+1 Me pegó. Aquí hay un [clon del segundo enlace] (http://www.vbmysql.com/articles/database-design/managing-hierarchical-data-in-mysql) con un mejor formato. ¡Aclamaciones! –

+0

@XavierHolt, gracias, actualicé el enlace. De hecho, estaba buscando la publicación original en mysql dev pero no pude encontrarla de nuevo. –

1

Esto no es posible en SQL puro y es uno de los aspectos de el modelo relacional que genera la mayoría de las críticas.

Yo recomendaría que lea los enlaces en este post: SQL "tree-like" query - most parent group

Y también, si su aplicación se basa demasiado en esto, yo le sugeriría a echar un vistazo a algunas bases de datos no relacionales que pueden representar este tipo de datos mucho mejor, como MongoDB (www.mongodb.org)

1

Espero haber entendido bien su pregunta (es bastante tarde aquí y acabo de llegar de un bar), si no lo hice, simplemente corrija yo y voy a reescribir mi respuesta.

Según la situación dada, creo que hay otra tabla principal, ¿no?

Imaginemos que sus atributos son identificación y nombre. La tabla de los niños es dada por ti (sin atributos innecesarios).

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 | 
+----+---------+--------+ 

Para hacer esto varias veces (el padre consiguió niño que consiguió un niño que consiguió un niño etc ...) Puede lograr eso usando múltiples uniones.

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 | 
+----+---------+--------+--------+ 

Si bien aún no ha i contesto lo que pidió o si necesita más explicación que me haga saber;]

Saludos,

Releis

Cuestiones relacionadas