Ver Mensaje Individual
  #16 (permalink)  
Antiguo 14/01/2009, 19:44
Avatar de gnzsoloyo
gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años, 3 meses
Puntos: 2658
Respuesta: Problema consulta group by y having

Bien, probé con tu estructura de tabla (tomada de este post), con el conjunto de datos que indicas en el último:
Cita:
codigo codigomatricula nombres curso paralelo mes valor
1270, 10116, 'CHANGO CUENCA YOLANDA ALEXANDRA', 'SEXTO', 'B', '11', 16
1280, 10660, 'ALAVA CEDEÑO ANDREA GABRIELA', 'SEXTO', 'B', '11', 16
1285, 10691, 'AVILA NARVAEZ ANGELICA ANDREA', 'SEXTO', 'B', '11', 16
7279, 10116, 'CHANGO CUENCA YOLANDA ALEXANDRA', 'SEXTO', 'B', '33', 16
7289, 10660, 'ALAVA CEDEÑO ANDREA GABRIELA', 'SEXTO', 'B', '33', 16
7294, 10691, 'AVILA NARVAEZ ANGELICA ANDREA', 'SEXTO', 'B', '33', 16
5277, 10116, 'CHANGO CUENCA YOLANDA ALEXANDRA', 'SEXTO', 'B', '22', 16
5287, 10660, 'ALAVA CEDEÑO ANDREA GABRIELA', 'SEXTO', 'B', '22', 16
5292, 10691, 'AVILA NARVAEZ ANGELICA ANDREA', 'SEXTO', 'B', '22', 16
y es cierto, no te lo devuelve, pero la razón es bastante simple:

Desglosemos:

1. Cuando hay una clave declarada y sobre todo la primaria, que en este caso es "codigo" y luego "codigomateria", si no hay un ORDER BY, MySQL ordena los resultados en función de esas claves, para luego ordenarlos sucesivamente y en orden de aparición por los diferentes campos.

2. Esto hace que el valor "11" sea el primero en aparecer para cada grupo de registros que coinciden en el "codigomateria", mas o menos en este orden:
Cita:
"codigo","codigomatricula","nombres","curso","para lelo","mes","valor"
1270,10116,"CHANGO CUENCA YOLANDA ALEXANDRA","SEXTO","B","11",16
1280,10660,"ALAVA CEDEÑO ANDREA GABRIELA","SEXTO","B","11",16
1285,10691,"AVILA NARVAEZ ANGELICA ANDREA","SEXTO","B","11",16
5277,10116,"CHANGO CUENCA YOLANDA ALEXANDRA","SEXTO","B","22",16
5287,10660,"ALAVA CEDEÑO ANDREA GABRIELA","SEXTO","B","22",16
5292,10691,"AVILA NARVAEZ ANGELICA ANDREA","SEXTO","B","22",16
7279,10116,"CHANGO CUENCA YOLANDA ALEXANDRA","SEXTO","B","33",16
7289,10660,"ALAVA CEDEÑO ANDREA GABRIELA","SEXTO","B","33",16
7294,10691,"AVILA NARVAEZ ANGELICA ANDREA","SEXTO","B","33",16
Como podrás ver, los "valor" que contienen el 33 se acumulan al final, por cuanto el resto de los campos tienen el mismo valor entre sí, salvando el nombre.

3. Como luego del WHERE hay un GROUP BY, esto hace que los registros de valores coincidentes en ese campo se agrupen dejando solamente el primero... cuyo valor en "valor" es 11. Todo el resto de los valores desaparecen.
El resultado es esto:
Cita:
"codigo","codigomatricula","nombres","curso","mes" ,"SUM(`valor`)"
1270,10116,"CHANGO CUENCA YOLANDA ALEXANDRA","SEXTO","11",48
1280,10660,"ALAVA CEDEÑO ANDREA GABRIELA","SEXTO","11",48
1285,10691,"AVILA NARVAEZ ANGELICA ANDREA","SEXTO","11",48
4. Finalmente, el HAVING opera sobre esa tabla resultado, por lo que al no haber ningún registro con campo "valor" en 22, no hay ningún registro devuelto. Suma cero.

¿Cómo se resuelve esto? De la misma forma en que hemos insistido con jurena: El `valor`= 22 va en el WHERE, no en el HAVING.
Si usas esta sentencia:
Código sql:
Ver original
  1. SELECT
  2.   `codigo`,
  3.   `codigomatricula`,
  4.   `nombres`,
  5.   `curso`,
  6.   `mes`,
  7.   SUM(`valor`)
  8. FROM meses
  9. WHERE curso = "sexto"
  10. AND paralelo = "b" AND MES=22
  11. GROUP BY `codigomatricula`;
obtendrás el resultado esperado.

Todo el problema es que estás suponiendo que la lógica de la consulta opera como un todo, y no es así. Ciertas cláusulas operan sobre los resultados intermedios.
Además, te repito, el HAVING no se usa para el uso que pretendes darle, sino para operar fundamentalmente sobre valores calculados o rangos de uno campo, pero en cualquier caso, operarán sobre el resultado final de la sentencia, no antes.

Respecto a que no sume los valores, no los sumará jamás si no hay más de un registro donde la misma persona (codigomateria) tenga curso = "SEXTO", paralelo="B" y mes=22... por la simple razón que estás agrupando por codigomateria, que parece ser clave de la persona. ¿Puede darse esa condición?
En los hechos, ese agupamiento carece de sentido.
Si lo que quieres es saber cuantos meses pagó cada uno, hay que agrupar por codigomateria, si deseas saber cuantos pagaron el mes, hay que agrupar por mes, y así. Pero agrupar por persona y restringir todos los valores clave, no produce ningún resultado.

Daría lo mismo que si hicieras esto:
Código sql:
Ver original
  1. SELECT
  2.   `codigo`,
  3.   `codigomatricula`,
  4.   `nombres`,
  5.   `curso`,
  6.   `mes`,
  7.   SUM(`valor`)
  8. FROM meses
  9. WHERE curso = "sexto"
  10. AND paralelo = "b" AND MES=22
  11. GROUP BY `nombres`;
o esto:
Código sql:
Ver original
  1. SELECT
  2.   `codigo`,
  3.   `codigomatricula`,
  4.   `nombres`,
  5.   `curso`,
  6.   `mes`,
  7.   `valor`
  8. FROM meses
  9. WHERE curso = "sexto"
  10. AND paralelo = "b"
  11. AND MES=22;
En definitiva es un problema de lógica, no de codificación. ¿Se comprende?
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Última edición por gnzsoloyo; 14/01/2009 a las 19:58