Filtrado de agregación

Having

Una vez que se obtiene información calculada sobre grupos de filas mediante el group by, se pueden filtrar estos resultados y mostrar sólo aquellos que nos interesen mediante la cláusula having. Having es a group by lo mismo que where a select-from

Al igual que la cláusula where selecciona filas, la cláusula having selecciona grupos; si, en where, la condición que se especifica afecta a las filas de toda la tabla, group by efectúa cálculos en función de esa selección previa, y da como resultado una tabla con la información calculada para cada grupo dentro de esa selección. Sobre esta última, having eliminaría aquellas filas que no cumplen la condición.

Podemos entender el proceso de una consulta con group by-having como la ejecución previa de la parte select-from-where y, a partir de este resultado intermedio, la obtención de la información calculada con group by y, finalmente, el filtrado con having

¿Cuántas asignaturas imparte cada profesor?

select p.dni, nombre, count(*) asignaturas

from profesores p, imparte i

where p.dni = i.dni

group by p.dni, nombre 

¿Cuántas asignaturas imparten los profesores con 2 o más asignaturas?

select p.dni, nombre, count(*) asignaturas

from profesores p, imparte i

where p.dni = i.dni

group by p.dni, nombre

having count(*) >= 2 

Sin tener en cuenta la asignatura FBD, ¿cuántas asignaturas imparten los profesores con 2 o más asignaturas?

select p.dni, nombre, count(*) asignaturas

from profesores p, imparte i

where p.dni = i.dni

and asignatura != 'FBD'

group by p.dni, nombre

having count(*) >= 2 

Paso a paso:



Ninguna fila seleccionada.

La condición del having no es necesariamente sobre el cálculo a mostrar, como se puede ver en el siguiente ejemplo.

¿Cuántas asignaturas imparte cada profesor en el caso de que la suma de créditos sea mayor que 5?

select p.dni, nombre, count(*) asignaturas

from profesores p, imparte i, asignaturas a

where p.dni = i.dni and a.codigo = i.asignatura

group by p.dni, nombre

having sum(creditos) > 5 

MariaDB/MySQL permite alejarse del SQL estándar

Nuestro servidor está configurado con @@SQL_MODE = 'ONLY_FULL_GROUP_BY'

Si estás trabajando contra tu propio servidor local, es posible que este modo SQL no esté configurado así, y sí darán resultado. Puedes modificar este comportamiento con set sql_mode = ''. Cuando cierres la conexión y te identifiques de nuevo en el servidor, la variable volverá a su valor anterior.

Hay que tener cuidado con una característica de MariaDB/MySQL que depende también de cómo esté configurado el servidor. El caso es que podría darse el caso de que MariaDB/MySQL acepte la siguiente orden en la que hemos omitido la columna nombre del group by:

DNI y nombre del coordinador y cuántas asignaturas coordina.

set @modo = @@SQL_MODE; -- para poder restaurar la configuración al final

set sql_mode = '';

select dni, nombre, count(*) coordina

from asignaturas a, coordinadores c 

where c.asig = a.codigo 

group by dni;  

set SQL_MODE = @modo; -- restaurada configuración

En este caso, no hay problema puesto que para cada dni hay un único nombre, dni es el identificador de los coordinadores, pero no siempre es así. Como en muchas otras cosas, MariaDB/MySQL ofrece funcionalidades propias que el usuario puede elegir o no, pero alejarse del estándar dificulta la posibilidad de migrar a otros sistemas de gestión de base de datos. MariaDB/MySQL deja en manos del que realiza la consulta el que tenga cuidado con el criterio de agrupación que utiliza asegurándose de que las columnas omitidas no van a alterar el resultado. Hay autores que defienden este "alejamiento" del estándar, como Roland Bouman.

Otra característica que MySQL permite por defecto es utilizar having sin group by:

set @modo = @@SQL_MODE; -- para poder restaurar la configuración al final

set sql_mode = '';

select * from asignaturas

having creditos > 3;

set SQL_MODE = @modo; -- restaurada configuración

La idea que subyace en esta "permisividad" es que where no permite utilizar funciones de agregado mientras que having sí. Nuevamente, esta extensión de MariaDB/MySQL no es aceptada por todos los gestores de BD.

En cualquier caso, no recomendamos estas prácticas, al menos en un contexto de aprendizaje básico, ni tampoco las aceptaremos en la evaluación de este tipo de ejercicios.