SQL - problemas con la select

 
Vista:
sin imagen de perfil

problemas con la select

Publicado por marcos (2 intervenciones) el 15/04/2015 20:56:22
Tengo una duda en hacer esta select.
Dispongo de estas 3 tablas:

Alumno
-id
-nombre

Matricula
-fk_alumno
-num_matricula
.fk_turno
-plazo

Turno
-id
-denominacion

*plazo, contiene 3 valores: 0,1 y 2
Mi pregunta es,¿como puedo sacar los datos del alumno cuya matricula tenga los plazos 0 y 2?
*Aporto un ejemplo real de mi base de datos

Cogo el alumno 101, que deberia mostrarse en la select porque el turno pertenece al 0 y 2.El 102 no cumple la condicion

alumno.id=101
alumno.nombre=juan
---
alumno.id=102
alumno.nombre=pepe
------------------------------
fk_alumno=101
fk_turno=18
plazo=0
---
fk_alumno=102
fk_turno=17
plazo=0
---
fk_alumno=102
fk_turno=18
plazo=1
---
fk_alumno=101
fk_turno=17
plazo=2
----------------------------
turno.id=17
turno.denomoniacion=matematicas
---
turno.id=18
turno.denomoniacion=historia

Mi select
Select al.nombre,ma.nm_matricula,tu.denominacion
From alumno al INNER JOIN matricula ma ON al.id=ma.fk_alumno
INNER JOIN turno tu ON ma.fk_turno= tu.id
WHERE al.id=ma.fk_alumno and ma.fk_turno= tu.id and ma.plazo='0' and ma.plazo='2'

No me muestra nada, ya que el plazo 0 es una fila y el plazo 2 es otra fila aunque pertenezcan al mismo alumno
Ayuda, por favor,Gracias
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Isaias
Val: 2.542
Oro
Ha mantenido su posición en SQL (en relación al último mes)
Gráfica de SQL

problemas con la select

Publicado por Isaias (1921 intervenciones) el 15/04/2015 21:14:36
ma.plazo='0' OR ma.plazo='2'
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil
Val: 806
Bronce
Ha mantenido su posición en SQL (en relación al último mes)
Gráfica de SQL

problemas con la select

Publicado por leonardo_josue (1173 intervenciones) el 15/04/2015 22:00:52
Hola Marcos:

Aclaremos algunos puntos antes de pasar a la solución. Si entendí bien, lo que quieres es mostrar aquellos alumnos que pertenecen al turno 0 y 2 a la vez... es decir, QUE TENGAN AMBOS... no aplica si tienen sólo el 0 o sólo el 2, ¿correcto?

Su estamos en ese contexto, la consulta que propone el compañero Isaías no funcionaría, ya que al colocar una condición OR, te regresaría aquellos alumnos que tienen sólo el turno 0, sólo el turno 2 o ambos... Además, hay que tener cuidado cuando mezclas condiciones AND y OR, ya que estas tienen una jerarquía distinta, esto quiere decir que no es lo mismo poner

1
tabla.campo = valor and tabla.campo2 = valor2 or tabla.campo3 = valor3


a poner

1
tabla.campo = valor and (tabla.campo2 = valor2 or tabla.campo3 = valor3)

En este mismo sentido, NO TIENE NINGUN CASO QUE EN EL WHERE VUELVAS A COLOCAR LA MISMA CONDICIÓN QUE TIENEN ES LA CLÁUSULA ON. Esto es completamente inutil.

Esto:

1
2
3
4
SELECT al.nombre,ma.nm_matricula,tu.denominacion
FROM alumno al INNER JOIN matricula ma ON al.id=ma.fk_alumno
INNER JOIN turno tu ON ma.fk_turno= tu.id
WHERE al.id=ma.fk_alumno and ma.fk_turno= tu.id and ma.plazo='0' and ma.plazo='2'

Es exactamente lo mismo a poner esto:

1
2
3
4
Select al.nombre,ma.nm_matricula,tu.denominacion
From alumno al INNER JOIN matricula ma ON al.id=ma.fk_alumno
INNER JOIN turno tu ON ma.fk_turno= tu.id
WHERE ma.plazo='0' and ma.plazo='2'

Ahora bien, pasando a tu pregunta, hay varias formas para obtener lo que quieres, la más común es agrupando y utilizando la cláusula HAVING... observa este ejemplo en mySQL. Supongamos que tienes los siguientes datos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> SELECT * FROM alumno;
+------+--------+
| id   | nombre |
+------+--------+
|  101 | juan   |
|  102 | pepe   |
|  103 | pedro  |
+------+--------+
3 rows in set (0.00 sec)
 
mysql> SELECT * FROM matricula;
+-----------+----------+-------+
| fk_alumno | fk_turno | plazo |
+-----------+----------+-------+
|       101 |       18 |     0 |
|       102 |       17 |     0 |
|       102 |       18 |     1 |
|       101 |       17 |     2 |
|       103 |       18 |     2 |
+-----------+----------+-------+
5 rows in set (0.00 sec)

Observa que el alumno JUAN tiene asociados tanto el turno 0 como el turno 2, el alumno PEPE tiene asociado sólo el turno 0 (aunque tiene asociado también el turno 1) y el alumno PEDRO tiene asociado sólo el turno 2.

Lo que puedes hacer es lo siguiente:

1
2
3
4
5
6
7
8
9
10
11
12
mysql> SELECT fk_alumno, COUNT(DISTINCT plazo)
    -> FROM matricula
    -> WHERE plazo IN (0, 2)
    -> GROUP BY fk_alumno;
+-----------+-----------------------+
| fk_alumno | COUNT(DISTINCT plazo) |
+-----------+-----------------------+
|       101 |                     2 |
|       102 |                     1 |
|       103 |                     1 |
+-----------+-----------------------+
3 rows in set (0.00 sec)

Esta consulta lo que hace es CONTAR cuantos registros del tipo plazo 0 o 2 tiene cada alumno, observa que aquí es claro que el alumno 101 tiene ambos plazos, mientras que los otros dos tienen sólo uno de ellos. Ahora simplemente tienes que filtrar con HAVING para obtener aquellos que tienen ambos:

1
2
3
4
5
6
7
8
9
10
11
mysql> SELECT fk_alumno, COUNT(DISTINCT plazo)
    -> FROM matricula
    -> WHERE plazo IN (0, 2)
    -> GROUP BY fk_alumno
    -> HAVING COUNT(DISTINCT plazo) = 2;
+-----------+-----------------------+
| fk_alumno | COUNT(DISTINCT plazo) |
+-----------+-----------------------+
|       101 |                     2 |
+-----------+-----------------------+
1 ROW IN SET (0.00 sec)

Finalmente, lo que haces es utilizar esta consulta para FILTRAR los registros originales... es decir, haces algo como esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> SELECT alumno.*
    -> FROM alumno
    -> INNER JOIN
    -> ( SELECT fk_alumno, COUNT(DISTINCT plazo) total
    ->   FROM matricula
    ->   WHERE plazo IN (0, 2)
    ->   GROUP BY fk_alumno
    ->   HAVING COUNT(DISTINCT plazo) = 2) T ON alumno.id = T.fk_alumno;
+------+--------+
| id   | nombre |
+------+--------+
|  101 | juan   |
+------+--------+
1 row in set (0.00 sec)

Dale un vistazo para ver si es más o menos lo que necesitas.

Saludos
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil

problemas con la select

Publicado por marcos (2 intervenciones) el 17/04/2015 10:21:47
Despues de realizar esta select:
SELECT alumno.nombre,alumno.apellidos,alumno.id
FROM alumno INNER JOIN
( SELECT fk_alumno, COUNT(DISTINCT plazo) total
FROM matricula
WHERE plazo IN (0, 2)
GROUP BY fk_alumno
HAVING COUNT(DISTINCT plazo) = 1) T ON alumno.id = T.fk_alumno

Comparo el id del alumno que me devuelve, en la tabla de matriculas y veo que los datos no coinciden.
Por ejemplo, visualizo el alumno 120 y veo que esta matriculado en 4 sitios y los datos del plazo no corresponden ya que me muestra 0,0,1,0, por lo tanto el operador IN no funciona ya que no coge los alumnos matriculados en los plazos 0 y 2. Por ejemplo, otro alumno que me muestra esta matriculado en 3 sitios y compruebo que su plazo son 1,1 y 2 y no deberia mostrarles.¿Alguna solucion?
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar