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

Consulta con 4 tablas

Estas en el tema de Consulta con 4 tablas en el foro de Mysql en Foros del Web. En primer lugar, muchas gracias a todos por los excelentes aportes que ofrecéis a través de este foro, ya que son de gran ayuda a ...
  #1 (permalink)  
Antiguo 01/12/2013, 19:44
 
Fecha de Ingreso: noviembre-2013
Mensajes: 13
Antigüedad: 11 años
Puntos: 0
Consulta con 4 tablas

En primer lugar, muchas gracias a todos por los excelentes aportes que ofrecéis a través de este foro, ya que son de gran ayuda a novatillos como yo.
La duda que os quiero plantear es sobre una consulta que necesito realizar sobre 4 tablas, pero que no me devuelve los resultados deseados. Intuyo que el problema son las relaciones establecidas entre las tablas, pero necesitaría la opinión de gente más experta que yo.

Veréis, tengo las siguientes cuatro tablas:

tabla USUARIOS, con los siguientes campos:
cod_usuario INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(50) NOT NULL,
apellidos VARCHAR(50),
login VARCHAR(10) NOT NULL UNIQUE, y varios campos más que no vienen al caso

tabla PRESTAMOS, con los siguientes campos:
cod_prestamo INT AUTO_INCREMENT PRIMARY KEY,
usuario INT NOT NULL,
FOREIGN KEY (usuario) REFERENCES usuarios (cod_usuario)
ON DELETE RESTRICT ON UPDATE RESTRICT,
fechaprest DATETIME NOT NULL,
tipo_prestamo ENUM('sala','externo') NOT NULL)";

TABLA 'TIENE' (Recoge los detalles de cada préstamo), con los siguientes campos:
prestamo INT NOT NULL,
FOREIGN KEY (prestamo) REFERENCES prestamos (cod_prestamo)
ON DELETE RESTRICT ON UPDATE RESTRICT,
ejemplar INT NOT NULL,
FOREIGN KEY (ejemplar) REFERENCES ejemplares (cod_ejemplar)
ON DELETE RESTRICT ON UPDATE RESTRICT,
libro INT NOT NULL,
FOREIGN KEY (libro) REFERENCES ejemplares (codigo_libro)
ON DELETE RESTRICT ON UPDATE RESTRICT,
devuelto TINYINT(1) DEFAULT 0,
fecha_dev DATETIME,
PRIMARY KEY(prestamo,ejemplar,libro))";

tabla SANCIONES, con los siguientes campos:
cod_sancion INT AUTO_INCREMENT PRIMARY KEY,
usuario INT NOT NULL,
FOREIGN KEY (usuario) REFERENCES usuarios (cod_usuario)
ON DELETE RESTRICT ON UPDATE RESTRICT,
prestamo INT NOT NULL,
FOREIGN KEY (prestamo) REFERENCES prestamos (cod_prestamo)
ON DELETE RESTRICT ON UPDATE RESTRICT,
fecha_sancion DATETIME NOT NULL,
importe INT NOT NULL,
pagada TINYINT(1) DEFAULT 0)

Lo que pretendo hacer es seleccionar aquellos usuarios que no tengan préstamos pendientes de devolver, y que tampoco tengan sanciones pendientes de pagar. Además, tampoco seleccionará al usuario cuya sesión está iniciada, que es el que está trabajando con la aplicación que utiliza esta base de datos. Para ello, tras darle muchas vueltas no lo he conseguido. En principio pensé en esta consulta:

Código MySQL:
Ver original
  1. SELECT u.cod_usuario cod_usuario, u.nombre nombre, u.apellidos apellidos, u.login login
  2. FROM sanciones s JOIN usuarios u
  3. ON s.usuario = u.cod_usuario
  4. JOIN prestamos p
  5. ON u.cod_usuario = p.usuario
  6. JOIN tiene t
  7. ON p.cod_prestamo = t.prestamo
  8. WHERE cod_usuario != ($_SESSION[cod_usuario]) AND (devuelto = 1) AND (pagada = 1)

¿Podéis echarme un cable?
Ahora que lo estoy pensando un poco más, después de estar toda la tarde machacándome (siempre después de un descanso se piensa mejor), aunque sólo mostrase los usuarios que no tengan préstamos o sanciones pendientes, sólo por el hecho de que aparezcan en dichas tablas, al ponerle RESTRICT en la definición de las claves externas no dejaría al usuario de la aplicación eliminar dichos usuarios. Tendría que ahondar un poco más, pero lo veo bastante enrevesado el tema.

Si alguien pudiera darme algunos consejos u orientaciones se lo agradezco de antemano.

Un saludo.

Última edición por gnzsoloyo; 02/12/2013 a las 03:12
  #2 (permalink)  
Antiguo 02/12/2013, 17:35
Avatar de marlanga  
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 10 meses
Puntos: 206
Respuesta: Consulta con 4 tablas

La tabla que manda es la de usuarios, así que es la única que tiene que aparecer en el FROM. Los JOIN son todos LEFT JOIN. Un join solo sacaría usuarios que tengan relación con alguna fila de la tabla con la que hagas el join, pero eso es falso en tu caso, porque habrá usuarios que no tengan prestamos, por ejemplo, y querrás que aparezcan en tu consulta.

Código MySQL:
Ver original
  1. SELECT u.*
  2. FROM usuarios u
  3. LEFT JOIN prestamo p ON u.cod_usuario=p.usuarion
  4. LEFT JOIN tiene t ON p.cod_prestamo=t.prestamo AND t.devuelto=1
  5. LEFT JOIN sanciones s ON u.cod_usuario=s.usuario AND s.pagada=1
  6. WHERE u.cod_usuario!= $_SESSION["cod_usuario"];
  #3 (permalink)  
Antiguo 04/12/2013, 20:50
 
Fecha de Ingreso: noviembre-2013
Mensajes: 13
Antigüedad: 11 años
Puntos: 0
Respuesta: Consulta con 4 tablas

Es cierto, marlanga!! Muchísimas gracias por aclararme un poco el tema.

Estaba tan empecinado en sacar a los usuarios cuyos préstamos y sanciones 'estuviesen a 1' (devueltos y pagadas), que no había reparado en que habrá usuarios que no habrán realizado préstamos todavía, o que nunca los hayan sancionado y con el JOIN de todas esas tablas nunca aparecerían.

De todas formas, el tema de las restricciones que he declarado para las claves foráneas estoy viendo que impedirán la eliminación de usuarios que hayan sido dados de alta en alguna de esas tablas (préstamos o sanciones), por lo que ahí si que no podría hacer nada.

Estoy construyendo todo esto pensando en la gestión de una biblioteca, donde un admin pudiese modificar o eliminar usuarios de la base de datos. La actualización no sería un problema al ponerle 'CASCADE' en la restricción, pero en la eliminación pienso que debo poner RESTRICT, ya que si no, podría darse el caso de borrar usuarios con sanciones o préstamos pendientes.

Seguiré dándole vueltas a eso.

Muchísimas gracias por la ayuda!!

Etiquetas: campo, join, null, select, tabla, tablas, usuarios
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 20:38.