Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

Consulta iterativa

Estas en el tema de Consulta iterativa en el foro de Mysql en Foros del Web. Buenas, estoy haciendo un sistema para subir archivos. Los guardo todos en una carpeta y como nombre les pongo el id de la base de ...
  #1 (permalink)  
Antiguo 31/07/2012, 17:10
 
Fecha de Ingreso: abril-2008
Mensajes: 12
Antigüedad: 16 años
Puntos: 2
Consulta iterativa

Buenas, estoy haciendo un sistema para subir archivos. Los guardo todos en una carpeta y como nombre les pongo el id de la base de datos. Su tabla resumida es esta:

CREATE TABLE `files` (
`id` int(11) NOT NULL,
`name` varchar(250) NOT NULL,
`folder` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)

Para simular las carpetas utilizo la siguiente tabla:

CREATE TABLE `folders` (
`id` int(11) NOT NULL,
`previous` int(11) DEFAULT NULL,
`name` varchar(250) NOT NULL,
PRIMARY KEY (`id`)
)

Como resulta evidente hay una foreign key entre files.folder y folders.id y otra entre folders.id y folders.previous

La idea es que al crear el archivo se pueda seleccionar como carpeta cualquier entrada de la tabla folders o NULL. Si es NULL, el archivo se encontraría en la raiz del sistema.
Del mismo modo si el campo 'previous' de la carpeta fuese NULL significa que la carpeta se encuentra en la raiz del sistema; y si indica un id, se encuentra dentro de la carpeta con ese id.

De este modo podría tener las siguientes entradas en folders:

INSERT INTO `folders` (`id`, `previous`, `name`) VALUES
(1, NULL, 'Carpeta 1'),
(2, 1, 'Subcarpeta para 1'),
(3, NULL, 'Carpeta 2'),
(4, 2, 'Sub sub carpeta de 1');

Bien, lo que quiero conseguir es una consulta que me devuelva el árbol de carpetas y su id, es decir, todas las carpetas con subcarpetas. Para el ejemplo anterior sería algo como:

1 /Carpeta 1
2 /Carpeta 1/Subcarpeta para 1
4 /Carpeta 1/Subcarpeta para 1/Sub sub carpeta de 1
3 /Carpeta 2

Para ello lo único que se me ocurre es formar un bucle de consultas que en caso de que previous sea distinto de NULL haga una consulta a ese id para averiguar su name y su previous y así sucesivamente hasta que sea distinto de NULL. Pero no tengo ni la menor idea de como lograrlo en MYSQL, y obviamente no lo quiero hacer en PHP...
Alguien sería tan amable de ayudarme Muchas gracias
  #2 (permalink)  
Antiguo 01/08/2012, 03:20
Usuario no validado
 
Fecha de Ingreso: abril-2008
Mensajes: 50
Antigüedad: 16 años
Puntos: 16
Respuesta: Consulta iterativa

Pensando en que sufra el programador antes que el servidor y la base de datos -con consultas recursivas-, podrías hacer algo así:

Tabla para registro de carpetas:
Id_Item int (PK)
Descripcion varchar
Nivel int
Correlativo int
CodGeneral varchar(200)
Id_Item_Ref int (FK a Tabla.Id_Item)

Datos
Código SQL:
Ver original
  1. Id_Item     Descripcion     Nivel   Correlativo CodGeneral      Id_Item_Ref
  2. ----------  --------------- ------- ----------------------      -----------
  3. 1           Madre 1         1       1           001             NULL
  4. 2           Hija 1          2       1           001001          1
  5. 3           Hija 2          2       2           001002          1
  6. 4           Nieta 1 x Hij1  3       1           001001001       2
  7. 5           Nieta 2 x Hij2  3       2           001002002       3
  8. 6           Madre 2         1       2           002             NULL

Ese campo "CodGeneral" lleva en 3 dígitos forzados por nivel el número de correlativo correspondiente.

Por ejemplo, "Nieta 1 x Hij2" en el nivel 3 tiene correlativo 2. Así que le corresponde "002". A esto le concatenas a la izquierda el CodGeneral de su ancestro inmediato "Hija 2" que es "001002" y te quedará "001002002".

Si haces un "select * from TABLA order by CodGeneral" tendrás la lista de carpetas y sub carpetas y sub sub..n carpetas en orden.

La cosa se complica cuando quieras mover una carpeta de lugar... Toca re-calcular todos los CodGeneral afectados.

Esto lo tengo ya implementado en más de un sitio web, así que te puedo garantizar que funciona ;)

OJO:
Ese CodGeneral debes ponerle una longitud suficiente para que no se "pase" de cierta cantidad de subniveles de carpeta. Y/o pararle los pies al usuario cuando intente agregar un tataranieto cuyo CodGeneral no quepa en el campo correspondiente.

También tenes que considerar que si "999" carpetas por carpeta no bastan, entonces en lugar de "a 3", los pones de "a 4" los pedazos de texto por nivel en cada CodGeneral.

De igual forma, si con "99" carpetas por carpeta vas sobrado, pues en lugar de "a 3" los pones de "a 2".

Etiquetas: php, sql, tabla, campos
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 04:23.