Crear o mejorar la estructura

Hola como va antes que nada muchas gracias por leer este post.
En realidad estoy tratando de generar un estructura de árbol, pero como mis conocimientos en sql, son básicos o medios, tal vez la experiencias les ha planteado algo similar.
Mi idea es crear algo como esto:
+- Primero (id=>1,nivel=>0,dependencia=>,estructura=> )
| |
| + - Otra cosa (id=>4,nivel=>1,dependencia=>1estructura=> 1 )
| |
| + - Algo (id=>5,nivel=>2,dependencia=>4,estructura=> 1_4 )
| |
| + - Algo más (id=>6,nivel=>2,dependecia=>4,estructura=> 1_4)
|
+- Segundo (id=>2,nivel=>0,dependencia=>,estructura=> )
|
+ Tercero (id=>3,nivel=>0,dependencia=>,estructura=> )
El tema es que quiero que sea indefinido, o sea que pueda crear tantos niveles como quiera.
Para esto mi idea fue crear cuatro campos:
Un id, nivel, dependencia, estructura.
En id guardo un numero auto incrementable correspondinte a cada valor ingresado.
Como nivel, especifico un número sobre a que nivel del árbol pertenece, empezando con 0.
Dependiencia, es un intenger que le asigno el valor inmediato superior de la rama, o sea de quien depende.
Y como estructura (un blob) guardo los id de cada nivel principal, hasta llegar al valor seleccionado, separados por un separador común en mi caso un undercore (_).
Si te fijas en los valores que puse al lado de cada rama, tal vez le queda más claro.
Bueno para resolverlo, hago dos consulta una leyendo el campo estructura perteneciente al id pasado con lo que genero (previo un pequeño proceso de desarme) un pedazo de una posterior consulta donde me da toda la rama hasta el valor que quiero.
Lo hago con algo como esto
'SELECT estructura FROM categoria id=' por ejemplo 4
Después obtengo hago una consulta donde busco todo los niveles 0, ademas de los id que recientemente obtuvimos y todo los valores de que dependan (campo dependencia) del id pasado, ademas del id que paso obviamente, con algo como esto:
'SELECT id,nivel,texto FROM categoria WHERE id="id pasado, ejemplo 4" AND dependencia="id pasado, ejemplo 4" AND nivel=0 y le sumo los resultados de la consulta previa como id="ejemplo 1"
Todo esto lo proceso y lo selecciono según pertenezca o no a el nivel cero si pertenece al nivel cero lo cargo a un array y si no lo cargo a otro, pero si pertenece al nivel cero me fijo si ese valor no esta dentro de un array asociativo de la primera consulta, si es así, creo una variable indicando cual es el campo, porque luego le voy a agregar una nueva entrada (ANEXO)con el array que no tiene nivel cero, un poco más gráfico, seria:
respuesta que creo:
array = (
[
ID=>1,
NIVEL=>0,
TEXTO=>'Primero',
ANEXO=>[
[ID=>4,NIVEL=>1,TEXTO=>'Otra cosa']
[ID=>5,NIVEL=>2,TEXTO=>'Algo']
[ID=>6,NIVEL=>2,TEXTO=>'Algo más']
]
],
[
ID=>2,
NIVEL=>0,
TEXTO=>'Segundo',
],
[
ID=>3,
NIVEL=>0,
TEXTO=>'Tercero',
]
)
Bueno, para que no se cansen, ¿acá va la pregunta?
Conoces o piensas en alguna forma mejor de hacerlo, estructurándolo de otro modo, la idea seria hacer todo en una consulta, aunque no es necesario seguir este formato, tal vez y solo tal vez la estructura de respuesta, aunque ideas seguramente tienes muchas y variadas.
Espero no haber sido más tedioso de lo necesario, te mando un gran saludo.
Y gracias por solo leerlo.

2 Respuestas

Respuesta
1
No se exactamente como quieres después mostrar los datos, pero te voy a plantear yo un ejemplo también.
Simplemente te hacen falta tres campos para la estructura en árbol: El Id, el Id_Padre y la Descripción. El Id, como tu has dicho, es autonumérico, mientras que el Id_Padre va a guardar el Id del nodo que cuelga. Así pues, por ejemplo en PHP sería así para obtener el árbol:
$usuario=root;
$pass='';
$odbc='Ejemplo';
$conexion=odbc_connect($usuario,$pass,$odbc);
/*Conecta mediante odbc con la base de datos, en este caso lo puedes sustituir por mysql_connect, aunque yo te lo haré con odbc que es general :)*/
$sql="SELECT * FROM Ejemplo WHERE Id_Padre=null";
/*Sentencia SQL que quieres ejecutar y en este caso con la que obtenemos los nodos primarios*/
$resultado=odbc_exec($conexion,$sql);
/*Ejecuta la sentencia en la base de datos con la cuál hemos conectado*/
while(odbc_fetch_row($resultado)){
$Id_Padre=odbc_result($resultado,"Id");
/*Obtenemos los Id de cada fila*/
$descripcion=odbc_result($resultado,"Descripcion");
echo "Nodo Padre: ",$Id_Padre . " " . $descripcion;
Funcion_Recursiva($Id_Padre,$conexion);
}
/*El while se ejecuta mientras haya registros que devolver pasando de uno en uno hasta el final*/
Funcion_Recursiva($Id,$Conexion){
$sql="SELECT * FROM Ejemplo WHERE Id_Padre=$Id";
$resultado=odbc_exec($Conexion,$sql);
while(odbc_fetch_row($resultado)){
$Id_Padre=odbc_result($resultado,"Id");
$descripcion=odbc_result($resultado,"Descripcion");
echo "Nodo Hijo: ",$Id_Padre . " " . $descripcion;
echo "Nodo del que dependo",$Id;
Funcion_Recursiva($Id_Padre,$Conexion);
}
}
Con eso obtendrás todo el árbol teniendo todos los nodos que quieras. Espero no haberte liado yo tampoco. Yo creo que si lo aplicas no fallará. Si encuentras algún problema te lo intentaré resolver.
Si mira en realidad, no quería toda la estructura de árbol sino, la estructura principal o sea el nivel cero y después desplegado la rama que quería, hasta el nivel que yo halla seleccionado, la idea era hacerlo con la menor cantidad de consultas, justamente plantee algo como lo tuyo.
Pero viste como somos por ahí buscamos mejorar la cosa, por esto, tuve una respuesta interesante.
Oracle, soporta una función que no esta implementada en otro, ojo no se en mssql, que es CONNECT BY PRIOR, con esta podes sacar una estrucura árbol sin procesar nada afuera, sino que la bd se encarga de armarla, en SQL 99 también fue definida como WITH RECURSIVE, exactamente se define en toda las documentación este tipo de consulta como consultas recursivas.
Espero que te sirva.
Y aprecio muchísimo tu respuesta
Gracias
Respuesta
1
No sé si todavaía te interesará el comentario, pero por si acaso, allá va.
Si quieres generar una estructura de árbol, hay otra forma. La estructura de la tabla debería tener un campo para el identificador del nodo y otro para el identificador del padre, a parte los campos que quieras de información. Para este ejemplo, al identificador lo llamaré nodo, al padre, ídem, y añadiré un tercer campo que será el supuesto valor, la tabla sería la siguiente:
Create table Tabla
(
Nodo number,
padre number,
valor number
)
Y para tener ejemplos, insertaremos estos valores:
insert into Tabla (NODO, PADRE, VALOR)
values (0, null, 3);
insert into Tabla (NODO, PADRE, VALOR)
values (1, 0, 2);
insert into Tabla (NODO, PADRE, VALOR)
values (2, 0, 6);
insert into Tabla (NODO, PADRE, VALOR)
values (3, 1, 1);
insert into Tabla (NODO, PADRE, VALOR)
values (4, 1, 4);
insert into Tabla (NODO, PADRE, VALOR)
values (5, 2, 5);
insert into Tabla (NODO, PADRE, VALOR)
values (6, 2, 7);
Bueno, pues ahora imagina que queremos saber todos los padres desde el nodo 6 hasta la raíz, pues con:
select *
from tabla
start with nodo = 6 connect by prior padre = nodo
Obtendremos lo que comentábamos.
Agradezco tu respuesta, hace un tiempo lo soluciones de esa misma forma, pero el problema que se me había presentado en aquel entonces es que utilizaba mysql y esa es una consulta recursiva así que no quedo otra que migrar a oracle.
Según comentaba en la página de mysql en un breve periodo, iba a incluir las consultas recursiva, no te sabría decir sdi actualmente esta soportado pero es para que lo tengan en cuenta.
Saludos y gracias

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas