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

[SOLUCIONADO] .:Realizar consulta devolviendo valores NULL:.

Estas en el tema de .:Realizar consulta devolviendo valores NULL:. en el foro de Mysql en Foros del Web. ¡Buenas compañer@s! Os comento, quiero realizar una consulta utilizando estas cuatro tablas: premisa, solucion_premisa, alumno y ejercicio. La operación consiste en: un "alumno" resuelve un ...
  #1 (permalink)  
Antiguo 26/11/2014, 14:11
 
Fecha de Ingreso: julio-2010
Mensajes: 23
Antigüedad: 13 años, 8 meses
Puntos: 0
.:Realizar consulta devolviendo valores NULL:.

¡Buenas compañer@s!

Os comento, quiero realizar una consulta utilizando estas cuatro tablas: premisa, solucion_premisa, alumno y ejercicio.

La operación consiste en: un "alumno" resuelve un ejercicio, el ejercicio está compuesto de una o varias premisas que se ubican en "premisa". Por cada premisa solucionada, se crea una tupla en "solución_premisa" con la solución dada por el alumno.

Cada tupla en "premisa" hace referencia a un id de ejercicio y cada tupla en "solucion_premisa" hace referencia al id de la premisa solucionada y al id del alumno que la solucionó.

La cuestión es que necesito obtener, dado un alumno concreto y un ejercicio concreto, la lista de premisas solucionadas y no solucionadas por dicho alumno. Esto significa que si el alumno no ha dado solución, necesitaría obtener en la consulta esa premisa sin solución, o sea, a NULL.

Se que los tiros van por usar INNER JOIN, LEFT JOIN o RIGHT JOIN, pero no doy con la tecla. ¿Alguna idea?

¡Gracias de antemano! ¡Un saludo!
  #2 (permalink)  
Antiguo 26/11/2014, 14:29
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: .:Realizar consulta devolviendo valores NULL:.

LEFT JOIN entre las alumno y solucion_premisa.
Ya que la solución_premisa sólo puede tener registyros relacinados si el alumno generó una solución, si no hizo el ejercicio no tendrá registros relacionados con el alumno

Es decir, mas o menos así (a vuelo de pájaro):
Código SQL:
Ver original
  1. SELECT ...
  2. FROM alumno A LEF JOIN solucion_premisa SP ON A.alumno_id = SP.alumno_id
  3. INNER JOIN premisa P ON SP.premisa_id = p.premisa_id
  4. INNER JOIN ejercicio E ON p.ejercicio_id = E.ejercicio_id
  5. WHERE [condiciones] OR SP.alumno_id IS NULL;
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #3 (permalink)  
Antiguo 26/11/2014, 15:11
 
Fecha de Ingreso: julio-2010
Mensajes: 23
Antigüedad: 13 años, 8 meses
Puntos: 0
Respuesta: .:Realizar consulta devolviendo valores NULL:.

¡Gracias gnzsoloyo por la ayuda! He probado el código modificándolo un poco pero no me devuelve las premisas sin solucionar. El código es el siguiente:

Código SQL:
Ver original
  1. SELECT *
  2.     FROM alumno A LEFT JOIN solucion_premisa SP ON A.idAlumno = SP.idAlumno
  3.     INNER JOIN premisa p ON p.idPremisa = SP.idPremisa
  4.     INNER JOIN ejercicio e ON e.idEjercicio = p.idEjercicio
  5.     WHERE p.idEjercicio = 19 AND (SP.idAlumno = 2 OR SP.idAlumno IS NULL)
¿Dónde puede estar el problema? ¡Me tiene loco ya!

Última edición por gnzsoloyo; 26/11/2014 a las 16:30
  #4 (permalink)  
Antiguo 26/11/2014, 16:34
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: .:Realizar consulta devolviendo valores NULL:.

Si la única relación entre Alumno y Premisa es a través de Solucion_Premisa, nunca te las devolverá.
Para devolverte algo debería existir una entidad Examen, la cual esté relacionada con Ejercicio, y el Alumno con Examen.
En esencia, el modelado de datos que tienes no cubre la posibilidad de relacionar transitivamente al Alumno con las Premisas de modo que si no las responde aparezcan como nulas.

¿Tienes el diagrama de talas o al menos el de entidades?
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #5 (permalink)  
Antiguo 26/11/2014, 18:01
 
Fecha de Ingreso: julio-2010
Mensajes: 23
Antigüedad: 13 años, 8 meses
Puntos: 0
Respuesta: .:Realizar consulta devolviendo valores NULL:.

Mmmm...mi intención es conseguir en una consulta las premisas que componen a un ejercicio, con la solución de cada premisa dada por un alumno concreto. De modo que si el alumno ha dado una respuesta, que aparezca, pero si aún no la contestó, que aparezca NULL sólo en el campo 'solucion' de la consulta.

Tablas:

|--------------|
| Premisa |
|--------------|
| idPremisa |
| idEjercicio |
| contenido |
|--------------|


|--------------|
| Ejercicio |
|--------------|
| idEjercicio |
| contenido |
|--------------|

|--------------|
| Alumno |
|--------------|
| idAlumno |
| contenido |
|--------------|

|---------------------------|
| Solucion_premisa |
|---------------------------|
| idPremisa |
| idAlumno |
| solucion |
|---------------------------|

Un saludo!
  #6 (permalink)  
Antiguo 26/11/2014, 18:23
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: .:Realizar consulta devolviendo valores NULL:.

Como te dije, te falta la relación entre el Alumno y el Ejercicio... Es obligatoria porque la solucion_premisa es una relacion ternaria que depende de Ejercicio, Alumno y Premisa. Pero es una Relación, no una Entidad (al menos según lo veo yo).
Como toda entidad de relación N:N:N, requiere una tabla física, peroeso es a nivel datos.

El modelo que tienes no puede cumplir con lo que quiere el ejercicio. Necesitas esa tabla relacional que lo vincule todo.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #7 (permalink)  
Antiguo 26/11/2014, 18:51
 
Fecha de Ingreso: julio-2010
Mensajes: 23
Antigüedad: 13 años, 8 meses
Puntos: 0
Respuesta: .:Realizar consulta devolviendo valores NULL:.

No lo termino de comprender. Se supone que ¿a través de solucion_premisa se puede ver la relación de un alumno con un ejercicio a través de premisa, no?
  #8 (permalink)  
Antiguo 26/11/2014, 19:31
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: .:Realizar consulta devolviendo valores NULL:.

A ve si se entiende cómo lo veo:
- Tienes N alumnos que pertenecen a la institución.
- Cada alumno debe responder a N exámenes o Ejercicios, y el mismo Ejercicio debe ser respondido por N Alumnos.
- Cada Ejercicio consiste en N consignas o Premisas a solucionar. Cada Premisa es respondida en N ejercicios, correspondiente a cada alumno.
- Cada premisa solucionada por cada alumno en cada examen se registra de forma unívoca, pero si no se ha solucionado no se registra.

En ese contexto, hay.
1. Relación N:N entre Alumnos y Ejercicios.
2. Relación N:N entre Ejercicio y Premisa.
3) Relación N:N.N entre Alumno, Ejercicio y Premisa.

DE acuerdo a este esquema se determina que existen las siguientes entidades:
1) Alumno(alumno_id, apellido, nombre, documento, ...)
2) Ejercicio(ejercicio_id, descripcion, ...)
3) Alumno_Ejercicio(alumno_id, ejercicio_id, fecha_ejercicio, ...)
4) Premisa(premisa_id, descripcion, ...)
5) Ejercicio_premisa(ejercicio_id, premisa_id, ...)
6) Premisa_solucion(alumno_id, ejercicio_id, premisa_id[, ...])

Para averiguar qué alumno no respondió una premisa hay que hacer una consulta bastante compleja...

Primero cruzar los alumnos con los exámenes:
Código MySQL:
Ver original
  1. SELECT ...
  2. FROM alumno A INNER JOIN alumno_ejercicio AE on A.alumno_id = ae.alumno_id
  3.    INNER JOIN ejercicio E ON AE.ejercicio_id = E.ejercicio_id;
Eso devolverá los ejercicios en los que participó.
Luego hay que cruzar eso con las premisas, que están el la quinta tabla, y si quieres los detalles con la cuarta, la de las premisas:
Código MySQL:
Ver original
  1. SELECT ...
  2. FROM alumno A INNER JOIN alumno_ejercicio AE on A.alumno_id = ae.alumno_id
  3.    INNER JOIN ejercicio E ON AE.ejercicio_id = E.ejercicio_id;
  4.    INNER JOIN ejercicio_premisa EP ON E.ejercicio_id = EP.ejercicio_id
  5.    INNER JOIN premisa P ON EP.premisa_id = P.premisa_id
Esto devuelve el listado completo de lo que compone el ejercicio, con todas sus premisas.
Recién en ese punto se puede resolver lo que quieres, pero esa relacion es múltiple por lo que el ON es más complejo:
Código MySQL:
Ver original
  1. SELECT ...
  2. FROM alumno A INNER JOIN alumno_ejercicio AE on A.alumno_id = ae.alumno_id
  3.    INNER JOIN ejercicio E ON AE.ejercicio_id = E.ejercicio_id;
  4.    INNER JOIN ejercicio_premisa EP ON E.ejercicio_id = EP.ejercicio_id
  5.    INNER JOIN premisa P ON EP.premisa_id = P.premisa_id
  6.    LEFT JOIN premisa_solucion PS ON P.premisa_id = PS.premisa_id AND A.alumno_id = PS.alumno_id AND E.ejercicio_id = PS.ejercicio_id
  7. WHERE [condiciones] AND (... OR PS.alumno_id IS NULL)

¿Se va entendiendo?

Se puede excluir la tabla de ejercicio_premisa si y sólo si una premisa sólo puede pertenecer a un único ejercicio. Eso es algo que dependerá de la definición del caso.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #9 (permalink)  
Antiguo 27/11/2014, 10:08
 
Fecha de Ingreso: julio-2010
Mensajes: 23
Antigüedad: 13 años, 8 meses
Puntos: 0
Respuesta: .:Realizar consulta devolviendo valores NULL:.

¡Buenas! ¡Ya lo he solucionado!

gnzsoloyo una premisa sólo pertenece a un ejercicio. Partiendo de tu solución, he elaborado una con las mismas tablas que ya partía, y por fin obtengo lo que quería. Como ejemplo, se indica el idEjericico a 19 y el idAlumno a 3. La solución sería:

Código SQL:
Ver original
  1. SELECT *
  2.     FROM premisa p INNER JOIN ejercicio e ON p.idEjercicio = e.idEjercicio
  3.     LEFT JOIN solucion_premisa sp ON sp.idPremisa = p.idPremisa AND sp.idAlumno = 3
  4.     WHERE e.idEjercicio = 19 OR (e.idEjercicio = 19 AND sp.idAlumno IS NULL)

¡Muchas gracias por la ayuda!¡Saludos!

Etiquetas: join, tabla
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

SíEste tema le ha gustado a 1 personas




La zona horaria es GMT -6. Ahora son las 08:34.