La cláusula HAVING
Ya vimos la consulta que obtiene el precio medio del alquiler de los alojamientos según su tipo:
MySQL 8.4SELECT home_type, AVG(price) as avg_price FROM Rooms GROUP BY home_type
Vamos a modificar esta consulta para que en el resultado solo aparezcan los grupos cuyo precio medio sea mayor que 50.
Con lo que ya sabes, es muy tentador usar la cláusula WHERE para esto. Pero si intentas ejecutar una consulta así, el SGBD devolverá inevitablemente un error y te indicará que la sintaxis WHERE avg_price > 50 no es correcta.
MySQL 8.4SELECT home_type, AVG(price) as avg_price FROM Rooms GROUP BY home_type WHERE avg_price > 50
Adelantando la respuesta: para filtrar grupos hay que usar la cláusula HAVING:
MySQL 8.4SELECT home_type, AVG(price) as avg_price FROM Rooms GROUP BY home_type HAVING avg_price > 50
MySQL 8.4SELECT home_type, AVG(price) as avg_price FROM Rooms GROUP BY home_type HAVING AVG(price) > 50
Orden de ejecución de una consulta SQL
Pero ¿por qué no podíamos usar WHERE y para qué hace falta una cláusula aparte? Todo se debe al orden en que se ejecuta una consulta SQL.

Nuestra primera consulta era incorrecta porque intentábamos usar la columna avg_price de los grupos antes de que se formaran, ya que la cláusula WHERE se ejecuta antes de la agrupación.
Es decir, en el momento de ejecutarse, WHERE no sabe nada de la agrupación posterior: solo trabaja con los registros de la tabla. Por eso podemos usarlo, por ejemplo, para filtrar por precio los registros de la tabla Rooms antes de agrupar y solo después calcular el precio medio de los grupos de alojamientos que quedan:
MySQL 8.4SELECT home_type, AVG(price) as avg_price FROM Rooms WHERE price > 50 GROUP BY home_type
Estructura general de una consulta con HAVING
SELECT campos_seleccion
FROM nombre_tabla
[WHERE condicion_filas]
GROUP BY campo_agrupacion [, ...]
HAVING condicion_grupos
[ORDER BY campo_ordenacion];- [ ]parte opcional
- ...se puede repetir
- campos_seleccion
Qué mostrar para cada grupo: literales, funciones de agregación y columnas de agrupación.
- nombre_tabla
- La tabla de la que se toman las filas.
- condicion_filas
Filtra las filas de la tabla antes de agrupar. En esta condición no puedes usar funciones de agregación.
Opcional- campo_agrupacion
La columna por la que las filas se dividen en grupos. Puedes indicar varias columnas separadas por comas.
- condicion_grupos
Filtra los grupos después de agrupar, por ejemplo COUNT(*) >= 5. En esta condición sí puedes usar funciones de agregación.
- campo_ordenacion
La columna o expresión por la que se ordena el resultado.
Opcional
Ejemplo de uso de HAVING
Como ejemplo, vamos a obtener el precio mínimo de cada tipo de alojamiento con televisor. Además, solo nos interesan los tipos de alojamiento que tengan al menos 5 alojamientos.
Para obtener este resultado, tenemos que:
-
Primero, obtener todos los datos de la tabla
MySQL 8.4SELECT ... FROM Rooms; -
Después, quedarnos solo con los registros de la tabla Rooms que nos interesan, es decir, solo los alojamientos con televisor
MySQL 8.4SELECT ... FROM Rooms WHERE has_tv = true -
A continuación, agrupar estos registros de alojamientos por su tipo
MySQL 8.4SELECT ... FROM Rooms WHERE has_tv = true GROUP BY home_type -
Luego, filtrar los grupos obtenidos según la condición. Nos interesan los grupos que tengan al menos 5 elementos
MySQL 8.4SELECT ... FROM Rooms WHERE has_tv = true GROUP BY home_type HAVING COUNT(*) >= 5 -
Y, por último, mirar qué pide la tarea y añadir la salida de la información necesaria. En nuestro caso, hay que mostrar el nombre del tipo de alojamiento y su precio mínimo.
MySQL 8.4SELECT home_type, MIN(price) as min_price FROM Rooms WHERE has_tv = true GROUP BY home_type HAVING COUNT(*) >= 5;