Volver a la lista de artículos Artículos
Lectura de 6 minutos

¿Qué es la cláusula HAVING en SQL?

¿Estás aprendiendo SQL? ¿Se pregunta para qué puede utilizar la cláusula cláusula HAVING? O, tal vez, ha intentado utilizar WHERE en sus agregados agregados GROUP BY? Está en el lugar adecuado. En este artículo, explicamos cómo utilizar HAVING con muchos ejemplos.

¿Ha intentado filtrar sus métricas creadas con GROUP BY con una cláusula WHERE y ha descubierto que no funciona? Esto es porque esto no es lo que hace WHERE. Necesita una cláusula HAVING.

En este artículo, explicaremos cómo utilizar HAVING para filtrar sus datos agregados. Aprenderá cuándo y cómo utilizarla, su sintaxis y la diferencia con WHERE. Se lo mostraremos con ejemplos detallados de una empresa de alquiler de películas.

¿Estás preparado? ¡Vamos a entrar en materia!

El conjunto de datos y el problema

En este artículo, utilizamos la tabla film del conjunto de datos de muestra de Sakila. Contiene una lista de películas que se pueden alquilar en un servicio ficticio de alquiler de DVD.

A continuación se muestra un ejemplo de consulta y su resultado.

SELECT
	title,
	release_year,
	language_id,
	rental_duration,
	length,
	rating
FROM
	film
LIMIT 10;
titlerelease_yearlanguage_idrental_durationlengthrating
ACADEMY DINOSAUR20061686PG
ACE GOLDFINGER20061348G
ADAPTATION HOLES20061750NC-17
AFFAIR PREJUDICE200615117G
AFRICAN EGG200616130G
AGENT TRUMAN200613169PG
AIRPLANE SIERRA20061662PG-13
AIRPORT POLLOCK20061654R
ALABAMA DEVIL200613114PG-13
ALADDIN CALENDAR20061663NC-17

Con estos datos, queremos ver qué tipos de películas alquila la gente por períodos más cortos o más largos. Esta información nos permitirá identificar el tipo de películas y el público en el que podríamos centrarnos.

AGRUPAR POR: Un resumen

Utilizamos HAVING en grupos creados con una cláusula GROUP BY.

Hagamos un rápido recordatorio de cómo agregamos los datos con GROUP BY. Utilizamos GROUP BY para resumir nuestros datos en métricas agregadas. Para ello necesitamos dos cosas:

  • Una función de agregación como COUNT, MAX, o AVG.
  • Una columna para agregar.

Por ejemplo, queremos saber cuántas películas tenemos en cada categoría de valoración. Para responder a esta pregunta, utilizamos COUNT(*) para contar el número de películas en cada grupo, y utilizamos GROUP BY para agregar esta métrica según los valores de la columna rating:

SELECT
	rating,
	COUNT(*) AS films
FROM
	film
GROUP BY rating
ORDER BY rating;
ratingfilms
G178
PG194
PG-13223
R195
NC-17210

El resultado muestra el número de películas por calificación. La distribución de las películas por clasificación es relativamente uniforme. La clasificación más popular es PG-13, mientras que la menos popular es G.

Para saber más sobre GROUP BY, consulta este artículo en profundidad o esta lista de ejemplos prácticos.

Ahora que hemos revisado lo que es GROUP BY, ¡podemos combinarlo con HAVING!

Cuándo usar HAVING de SQL

El uso principal de la operación HAVING es para filtrar datos agregados. Puede utilizarla cuando resume sus datos con GROUP BY en nuevas métricas, y desea seleccionar los resultados basados en estos nuevos valores.

Es similar a WHERE, pero se utiliza en diferentes circunstancias. Al final de este artículo, leerás más sobre esta diferencia en detalle.

La sintaxis HAVING de SQL

En términos de sintaxis, HAVING sólo requiere una línea después de GROUP BY. El siguiente fragmento resume la sintaxis necesaria para utilizar una cláusula HAVING:

SELECT
	aggregate_function(column)
FROM
	table
GROUP BY column_to_aggregate_on
HAVING condition_on_aggregate_metric;

Esta sintaxis es concisa, pero veamos cómo funciona a través de ejemplos.

Ejemplos de HAVING

Supongamos que queremos saber qué películas alquilan las personas durante más o menos tiempo. Podríamos estar interesados en la duración del alquiler por calificación. Por ejemplo, centrarnos en las películas con alquileres más cortos podría permitirnos tener una facturación global más rápida. Veamos qué pueden decirnos los datos sobre esta cuestión.

Creamos dos métricas agregadas agrupadas por calificación. A continuación, utilizamos HAVING para filtrar la tabla resultante en función de la duración media de los alquileres (avg_rentdur).

SELECT
	rating,
	COUNT(*) AS films,
	AVG(rental_duration),
	AVG(length)
FROM
	film
GROUP BY rating
HAVING AVG(rental_duration) > 5

HAVING Aquí se seleccionan los datos en base a una condición sobre un grupo que creamos con una función agregada (AVG).

ratingfilmsAVG(rental_duration)AVG(length)
PG1945.0825112.0052
NC-172105.1429113.2286
PG-132235.0538120.4439

El resultado no incluye las clasificaciones G y R, porque su duración media de alquiler es inferior a 5 días. La gente alquila películas con clasificación PG, PG-13 o NC-17 durante períodos más largos.

¡Interesante!

Ya que estamos mirando las categorías por su duración de alquiler, vamos a filtrar más nuestros resultados. También eliminaremos las clasificaciones cuya duración media sea superior a dos horas. Lo hacemos añadiendo otra condición de grupo a la cláusula HAVING:

SELECT
	rating,
COUNT(*) AS films,
AVG(rental_duration),
AVG(length)
FROM
	film
GROUP BY rating
HAVING AVG(rental_duration) > 5
	AND AVG(length) < 120;

La condición adicional en AVG(length) filtra la clasificación PG-13.

ratingfilmsAVG(rental_duration)AVG(length)
PG1945.0825112.0052
NC-172105.1429113.2286

Bien hecho.

No se puede utilizar WHERE para filtrar grupos

Mencionamos que HAVING es similar a WHERE, pero los usamos en diferentes escenarios. Veamos cómo funciona esto en nuestro ejemplo.

Reemplacemos HAVING por WHERE en la consulta que acabamos de escribir:

SELECT
	rating,
	COUNT(*) AS films,
	AVG(rental_duration),
	AVG(length)
FROM
	film
GROUP BY rating
WHERE AVG(rental_duration) > 5

Sin embargo, esto da como resultado el siguiente mensaje de error

ERROR 1064 (42000): Tiene un error en su sintaxis SQL; consulte el manual correspondiente a su versión del servidor MySQL para conocer la sintaxis correcta que debe utilizar cerca de 'WHERE avg_rentdur > 5' en la línea 9

Esto se debe a que las cláusulas GROUP BY se ejecutan después de las cláusulas WHERE. Esta consulta intenta aplicar WHERE en avg_rentdur cuando avg_rentdur aún no existe.

Esto significa que sólo podemos utilizar WHERE en los datos "brutos" y no en los valores agregados. Tenemos que utilizar HAVING en las métricas agregadas.

Uso de WHERE y HAVING en una consulta

Hemos visto que utilizamos WHERE para filtrar filas individuales y HAVING para filtrar grupos. Para demostrar su diferencia, veamos un ejemplo en el que utilizamos tanto HAVING como WHERE.

Queremos saber cómo cambian nuestros resultados anteriores cuando nos centramos en las películas cortas. Para ello, limitamos la duración de la película a 60 minutos.

En nuestra consulta, lo hacemos aplicando WHERE a la columna de duración:

SELECT
	rating,
	COUNT(*) AS films,
	AVG(rental_duration),
	AVG(length)
FROM
	film
WHERE
	length < 60
GROUP BY rating
HAVING AVG(rental_duration) < 5;
ratingfilmsAVG(rental_duration)AVG(length)
G214.381053.0952
NC-17214.904851.3810
R114.636455.0000

Los resultados muestran que si nos centramos sólo en las películas cortas, encontramos varias películas clasificadas como NC-17 con alquileres cortos de media. Este hallazgo puede darnos ideas sobre el tipo de películas que podemos introducir en nuestra futura selección de ofertas.

¿Quieres saber más sobre las diferencias entre HAVING y WHERE? Consulte nuestro artículo detallado sobre el tema.

¡Más información sobre SQL HAVING!

¿Te gusta lo que acabas de aprender? ¡Asegúrate de no olvidarlo! La mejor manera de aprender SQL es resolviendo problemas a través de ejemplos nuevos y desafiantes. Puedes configurar el mismo entorno de pruebas que utilizamos aquí, importar el mismo conjunto de datos y reescribir las consultas que acabas de aprender.

Sin embargo, eso podría requerir mucho trabajo, y sólo estarías recreando los mismos ejemplos. En su lugar, le recomendamos que consulte nuestro curso de práctica. Te ayudará a practicar el SQL HAVING y otras cláusulas a través de nuevos y desafiantes ejemplos.

¿Qué te parece? ¿Te animas?