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

Introducción a la cláusula HAVING de SQL: Un Tutorial para Principiantes

Así que eres nuevo en SQL y te acabas de topar con la cláusula CLÁUSULA HAVING HAVING. Pero, ¿qué hace? ¿Por qué es esencial? En este artículo, profundizaremos en los conceptos básicos de la cláusula CLÁUSULA HAVING en SQL. Además, realizaremos ejercicios prácticos para mejorar la comprensión de su funcionalidad.

Empecemos por definir el lenguaje de consulta estructurado (SQL). SQL es un lenguaje de programación potente y estandarizado diseñado específicamente para gestionar y manipular bases de datos relacionales; en pocas palabras, es la forma en que nos comunicamos con las bases de datos que contienen todos nuestros datos importantes. Con estos sistemas de bases de datos podemos realizar diversas tareas, como consultar, actualizar y gestionar datos.

SQL es esencial para una gestión y un análisis eficaces de los datos. Nos permite recuperar información específica, manipular datos en bases de datos y crear estructuras de bases de datos. SQL ofrece un potente conjunto de herramientas para extraer información relevante y generar informes en el análisis de datos. Puede obtener más información sobre estas bases de datos en nuestro artículo ¿Qué es una base de datos SQL?

SQL tiene palabras clave y cláusulas (comandos) específicas que nos ayudan a realizar estas acciones, de forma muy parecida a la gramática y las construcciones de un lenguaje escrito. Un ejemplo es la cláusula HAVING. En SQL, la cláusula HAVING es útil para refinar resultados de consultas filtrando grupos de datos basados en condiciones específicas. En este artículo, repasaremos algunos ejercicios para principiantes con la cláusula HAVING para ayudarte a empezar; para una explicación más detallada, consulta nuestro artículo Explicación de la cláusula HAVING de SQL.

Si está pensando en iniciar su andadura en SQL pero no sabe por dónde empezar, nuestro curso de SQL para principiantes es un excelente punto de partida. En este curso, aprenderás los fundamentos de SQL recuperando datos de bases de datos y creando informes sencillos utilizando ejemplos interactivos y del mundo real. Dicho esto, vamos a profundizar en la cláusula SQL HAVING.

La Cláusula HAVING

La cláusula HAVING trabaja en conjunto con la cláusula GROUP BY para limitar los resultados basados en funciones agregadas. Las funciones agregadas son herramientas SQL que nos permiten calcular valores como el total (SUM), la media (AVG) y el valor más bajo (MIN) a partir de grupos de filas de nuestros datos.

Vamos a explicar estas cláusulas con un ejemplo. Imaginemos que tenemos una tabla sales que almacena los informes de ventas de nuestra empresa. Podemos utilizar la siguiente consulta para encontrar regiones con ventas totales superiores a 10.000 dólares:

SELECT Region, SUM(TotalSales) as TotalSales
FROM Sales
GROUP BY Region
HAVING SUM(TotalSales) > 10000;

He aquí el desglose:

  • SELECT Region, SUM(TotalSales) as TotalSales: La cláusula SELECT muestra tanto la columna región como la suma total de ventas.
  • FROM Sales: La cláusula FROM especifica la tabla de origen - aquí, sales.
  • GROUP BY Region: La cláusula GROUP BY agrupa los datos basándose en la columna Región. Por ejemplo, si tenemos los valores "Francia", "Italia" y "España" en la columna Region, tendremos tres grupos.
  • HAVING SUM(TotalSales) > 10000: La cláusula HAVING especifica que los datos agregados para ese valor de columna (es decir, todas las ventas de "Italia") deben tener unas ventas totales superiores a $10,000 para que se incluyan en nuestro conjunto de resultados. Si las ventas totales de una región fueran inferiores a esta cantidad, no aparecería en los resultados de nuestra consulta.

Con HAVING, podemos refinar los resultados de la consulta filtrando los datos agregados (agrupados) en función de las condiciones que especifiquemos. Esto permite a los usuarios centrarse en subconjuntos de datos que cumplen criterios específicos, lo que permite extraer información significativa de los conjuntos de datos.

Quizás haya oído que la cláusula WHERE se utiliza en SQL para filtrar datos. ¿Cuál es la diferencia entre estas dos cláusulas? ¿Cuál debería utilizar?

En SQL, las cláusulas HAVING y WHERE son importantes para filtrar datos, pero se utilizan en distintas fases de la consulta. Para obtener más información, consulte nuestro artículo ¿Cuál es la diferencia entre las cláusulas WHERE y HAVING en SQL? Por ahora, veamos algunos ejemplos.

Modifiquemos ligeramente la consulta anterior. Esta vez, estamos calculando las ventas totales de cada región en 2023:

SELECT Region,SUM(TotalSales) as TotalSales
FROM Sales
WHERE YEAR(SaleDate) = 2023
GROUP BY Region;
In this version, the WHERE clause filters individual rows before they are grouped to include only those with a sale date in 2023. Now, let’s include both the WHERE and HAVING clauses:
SELECT Region, SUM(TotalSales) as TotalSales
FROM Sales
WHERE YEAR(SaleDate) = 2023
GROUP BY Region
HAVING SUM(TotalSales) > 10000;

Aquí la cláusula WHERE filtra filas individuales en función de la fecha de venta. Después de aplicar GROUP BY, la cláusula HAVING garantiza que sólo se incluyan en el resultado final las regiones con ventas totales superiores a 10.000 dólares en 2023.

En resumen:

  • WHERE se utiliza para filtrar filas individuales, reduciendo los datos antes de la agregación.
  • HAVING se utiliza para filtrar grupos de filas; se aplica a los grupos formados por agregación.

Ejemplo de consulta con HAVING

La mejor forma de aprender un lenguaje es practicando, por lo que en esta sección veremos algunos ejemplos prácticos que nos ayudarán a explicar la cláusula HAVING en su contexto. Si eres completamente nuevo en consultas SQL, echa un vistazo a nuestra SQL para principiantes Cheat Sheet para ayudarte a navegar por las siguientes consultas.

Ejercicio 1: Clientes con más de una compra

Ejercicio: Tiene los datos de compra de una tienda online y el equipo de análisis de la tienda quiere identificar a los clientes que tienen varias compras, es decir, encontrar a los clientes que vuelven. Muestra los ID de los clientes y el número de compras que han realizado.

Solución:

SELECT customer_id, COUNT(purchase_id) as purchase_count
FROM purchases
GROUP BY customer_id
HAVING COUNT(purchase_id) > 1;

Solución Explicación:

  • SELECT customer_id, COUNT(purchase_id) as purchase_count: La cláusula SELECT muestra los ID de los clientes y el número de compras.
  • FROM purchases: Especifica la tabla de origen como purchases.
  • GROUP BY customer_id: Agrupa los datos de compra por los ID de cliente, creando un grupo para cada cliente.
  • HAVING COUNT(purchase_id) > 1: La cláusula HAVING filtra el conjunto de resultados, incluyendo sólo los clientes que han realizado más de una compra.

Resultado:

customer_idpurchase_count
1035
1092
1113

Esta consulta destaca los clientes que han realizado más de una compra - o los clientes que vuelven. La cláusula HAVING es fundamental porque filtra a los clientes que sólo han realizado una compra. Sin HAVING, la consulta devolvería todos los clientes.

Ejercicio 2: Reconocimiento de Clientes Leales

Ejercicio: El director de una tienda de ropa online desea premiar a los clientes que hayan realizado al menos diez compras en 2023. Se le ha pedido que muestre el ID de cliente y el número de pedidos de los clientes que realizaron más de 10 pedidos el año pasado. Además, asegúrese de que el cliente con más pedidos aparezca en la parte superior de los resultados.

Solución:

SELECT customer_id, COUNT(order_id) as order_count
FROM orders
WHERE YEAR(order_date) = 2023
GROUP BY customer_id
HAVING COUNT(order_id) > 10
ORDER BY OrderCount DESC;

Solución Explicación:

  • SELECT customer_id, COUNT(order_id) as OrderCount: La cláusula SELECT muestra el ID del cliente y su número de pedidos.
  • FROM orders: Especifica la tabla de origen como orders.
  • WHERE YEAR(order_date) = 2023: Esto filtra las filas para incluir sólo pedidos desde 2023.
  • GROUP BY customer_id: Esto agrupa los datos por el ID del cliente, creando un grupo para cada cliente.
  • HAVING COUNT(order_id) > 10: Esta cláusula restringe el conjunto de resultados a los clientes con más de diez pedidos.
  • ORDER BY OrderCount DESC: Esto ordena los resultados por el número de pedidos en orden descendente (10-1) para que el cliente con el mayor número de pedidos vaya primero.

Resultado:

customer_idorder_count
121415
113514
115612

Esta consulta devuelve una lista de clientes que realizaron al menos diez compras el año pasado, con el cliente con más pedidos en la parte superior de los resultados. La cláusula HAVING es importante en este caso porque limita los resultados a los clientes leales que han realizado más de diez pedidos. Sin la cláusula HAVING, la consulta devolvería todos los clientes, independientemente del número de pedidos.

Ejercicio 3: Top Productos por Ventas

Ejercicio: El director de ventas de una tienda de muebles quiere identificar los productos que más venden. Para los productos con ventas superiores a 10.000 dólares, muestra el ID del producto así como el importe total vendido. Además, asegúrese de que los productos con mayores ventas aparecen en la parte superior de los resultados.

Solución:

SELECT product_id, SUM(sales_amount) as total_sales
FROM sales
GROUP BY product_id
HAVING SUM(sales_amount) > 10000
ORDER BY total_sales DESC;

Solución Explicación:

  • SELECT product_id, SUM(sales_amount) as total_sales: La cláusula SELECT muestra tanto el ID del producto como las ventas totales.
  • FROM sales: Esto especifica la tabla de origen como sales.
  • GROUP BY product_id: Agrupa los datos por ID de producto, creando un grupo para cada producto.
  • HAVING SUM(sales_amount) > 10000: La cláusula HAVING filtra el conjunto de resultados para incluir sólo productos con ventas totales superiores a 10.000 dólares.
  • ORDER BY total_sales DESC: Esto ordena los resultados por ventas totales en orden descendente, asegurando que los productos con más ventas aparezcan primero.

Resultados:

product_idtotal_sales
10218300
10515600
16012200

Esta consulta devuelve una lista de los productos con mejores resultados, mostrando los productos con ventas superiores a 10.000 dólares y ordenando las filas en orden descendente por ventas totales.

La cláusula HAVING es necesaria aquí porque nos permite filtrar el conjunto de resultados utilizando datos agregados, concretamente las ventas totales. Sin la cláusula HAVING, no podríamos filtrar los resultados basándonos en las ventas totales de cada producto. La cláusula WHERE no es adecuada para esta tarea porque filtra las filas antes de la agrupación; nos interesan las condiciones aplicadas a los datos agregados después de la agrupación.

Ejercicio 4: Valoración media por género

Ejercicio: Un crítico de cine quiere identificar los géneros de películas con valoraciones medias altas en 2020. Se le ha pedido que muestre los géneros de películas y las valoraciones medias de aquellos géneros valorados por encima de 4,0. Además, asegúrese de que los géneros con las valoraciones medias más altas aparecen en la parte superior.

Solución:

SELECT genre, AVG(rating) as avg_rating
FROM movies
WHERE YEAR(release_date) = 2020
GROUP BY genre
HAVING AVG(rating) > 4.0
ORDER BY avg_rating DESC;

Explicación:

  • SELECT genre, AVG(rating) as avg_rating: La cláusula SELECT muestra el género de la película y la calificación media.
  • FROM movies: Especifica la tabla de origen como movies.
  • WHERE YEAR(release_date) = 2020: Filtra las filas para incluir sólo las películas estrenadas en el año 2020.
  • GROUP BY género: Agrupa los datos por género, creando un grupo para cada género.
  • HAVING AVG(rating) > 4.0: Esto filtra el conjunto de resultados para incluir sólo géneros con una calificación media superior a 4,0.
  • ORDER BY avg_rating DESC: Ordena los resultados por puntuación media en orden descendente, asegurándose de que los géneros con las puntuaciones medias más altas estén en la parte superior.

Resultado:

genreavg_rating
Drama4.5
Comedy4.2

Esta consulta ayuda al crítico de cine a identificar los géneros cinematográficos excepcionales con una calificación media superior a 4,0 en 2020. El conjunto de resultados incluye cada género y su calificación media, que se ordenan en orden descendente en función de la calificación media.

La cláusula HAVING es esencial porque nos permite filtrar géneros basándonos en datos agregados (la valoración media).

Ejercicio 5: Identificación de usuarios con duraciones de inicio de sesión prolongadas

Ejercicio: Utilizando los datos de inicio de sesión de los usuarios de un sitio web, el equipo de seguridad informática trata de identificar a los usuarios con duraciones de inicio de sesión únicas inusualmente largas; esto les permite realizar una supervisión y un análisis exhaustivos de la seguridad. Muestra los nombres de los usuarios, sus direcciones de correo electrónico y la duración de su sesión de inicio de sesión más larga. Tenga en cuenta sólo a los usuarios cuyos tiempos de inicio de sesión superen las dos horas (7200 segundos). Además, asegúrese de que los usuarios con la mayor duración de inicio de sesión aparecen en la parte superior de los resultados.

Solución:

SELECT 
  users.user_name, 
  users.email_address, 
  MAX(logins.login_duration) as longest_login_duration
FROM users
JOIN logins 
ON users.user_id = logins.user_id
GROUP BY users.user_name, users.email_address
HAVING MAX(logins.login_duration) > 7200
ORDER BY longest_login_duration DESC;

Explicación:

  • SELECT users.user_name, users.email_address, MAX(logins.login_duration) as longest_login_duration: La cláusula SELECT muestra los nombres de usuario, las direcciones de correo electrónico y la duración de su sesión de inicio de sesión más larga.
  • FROM users: Esto especifica la tabla de origen como users.
  • JOIN logins ON users.user_id = logins.user_id: Realiza una unión interna entre las tablas users y logins basándose en el ID de usuario.
  • GROUP BY users.user_name: Esto agrupa los datos por los nombres de usuario, creando un grupo para cada usuario.
  • HAVING MAX(logins.login_duration) > 7200: La cláusula HAVING filtra el conjunto de resultados, incluyendo sólo los usuarios con duraciones de inicio de sesión superiores a 2 horas (7200 segundos).
  • ORDER BY longest_login_duration DESC: Esto ordena el resultado por la mayor duración de inicio de sesión, en orden descendente.

Resultado:

user_nameemail_addresslongest_login_duration
marty_89ff_7799@mail.com9067
scott_32scott_oc@mail.com7591
rachel_2003ray_hhh@mail.com7231

Esta consulta proporciona al equipo de seguridad informática los nombres de los usuarios, sus direcciones de correo electrónico y la duración de sus sesiones de inicio de sesión más largas. Sólo se muestran los usuarios con sesiones más largas para aumentar el control de seguridad.

En este caso, la cláusula HAVING es importante porque nos permite filtrar el conjunto de resultados basándonos en datos agregados, concretamente en la duración máxima de inicio de sesión alcanzada por cada usuario. Como queremos identificar a los usuarios que han iniciado sesión durante más de dos horas, la cláusula HAVING nos permite imponer esta condición a la duración máxima de inicio de sesión.

Casos de uso habituales de HAVING

La cláusula HAVING de SQL es una herramienta fundamental en situaciones reales en las que el análisis de datos, los informes y la inteligencia empresarial son importantes. Veamos algunos casos de uso comunes que demuestran la versatilidad de HAVING.

1. Segmentación de clientes

Las empresas se benefician de la comprensión de los diferentes grupos de clientes para poder orientar sus esfuerzos de marketing. La creación de segmentos de clientes permite elaborar estrategias a medida, lo que mejora la satisfacción del cliente.

Utilizando HAVING, podemos filtrar clientes de alto valor basándonos en umbrales de compra:

SELECT customer_id, SUM(purchase_amount) as total_purchase
FROM purchases
GROUP BY customer_id
HAVING SUM(purchase_amount) > 500;

2. Análisis del rendimiento de los empleados

Los profesionales de RRHH pueden utilizar SQL para ayudar a evaluar el rendimiento de los empleados. Esto facilita evaluaciones de rendimiento justas y específicas.

Utilizando la siguiente consulta, podemos encontrar empleados que hayan completado más de un determinado número de proyectos:

SELECT employee_id, COUNT(project_id) as completed_projects
FROM projects
GROUP BY employee_id
HAVING COUNT(project_id) >= 5;

3. Seguimiento de las ventas de productos

Para garantizar una gestión eficaz del inventario, las empresas necesitan realizar un seguimiento de los productos con mejores resultados. Esto puede ayudarles a identificar los artículos más vendidos y a asignar los recursos de forma más eficaz.

Mediante la siguiente consulta, podemos filtrar los productos cuyas ventas superen un determinado umbral:

SELECT product_id, SUM(sales_quantity) as total_sales
FROM sales	
GROUP BY product_id
HAVING SUM(sales_quantity) > 50;

4. Seguimiento de la asistencia a eventos

Los organizadores de eventos pueden querer identificar a los asistentes más comprometidos, es decir, aquellos que han asistido a más de un evento. Encontrar información sobre estos asistentes puede ayudar a planificar futuros eventos.

El uso de HAVING en la siguiente consulta nos permite identificar a los asistentes más comprometidos en función del número de eventos a los que han asistido:

SELECT attendee_id, COUNT(event_id) as attended_events
FROM event_attendance
GROUP BY attendee_id
HAVING COUNT(event_id) > 3;

5. Control de calidad en la fabricación

En la fabricación, el control de calidad es esencial para producir productos de alta calidad. Especificando umbrales en sus consultas SQL, el equipo puede garantizar la calidad de sus productos.

Utilizando HAVING en la siguiente consulta, podemos identificar los productos con tasas de defectos inferiores al límite especificado:

SELECT product_id, AVG(defect_rate) as avg_defect_rate
FROM manufacturing_quality
GROUP BY product_id
HAVING AVG(defect_rate) > 0.02;

Consejos para solucionar problemas con la cláusula HAVING

El uso de la cláusula HAVING en SQL a veces puede dar lugar a errores comunes, especialmente si está empezando. A continuación se ofrecen algunos consejos para solucionar posibles problemas:

Orden de las sentencias SQL

Cuando se comienza con consultas SQL, es común cometer errores con el orden de las sentencias. Asegúrese siempre de que su consulta sigue este orden:

SELECT column1, COUNT(column2) as count_column2
FROM my_table
WHERE condition
GROUP BY column1
HAVING COUNT(column2) > 10
ORDER BY column1;

No Agrupar Datos

Cuando se utiliza la cláusula HAVING, los datos deben ser agrupados primero utilizando la cláusula GROUP BY. La siguiente consulta resultaría en un error porque no tiene GROUP BY:

SELECT category, COUNT(product_id) as product_count
FROM products
HAVING COUNT(product_id) > 5;

Inconsistencia de SELECT y GROUP BY

La columna no agrupada de la sentencia SELECT debe incluirse en la cláusula GROUP BY. El ejemplo siguiente demuestra que como la categoría no está agregada, debe incluirse en la cláusula GROUP BY.

SELECT category, COUNT(product_id) as product_count
FROM products
GROUP BY category
HAVING COUNT(product_id) > 5;

Uso incorrecto de las condiciones HAVING

La siguiente consulta se ejecutará sin errores, pero no sigue las prácticas recomendadas. La cláusula HAVING se utiliza para filtrar resultados basados en valores agregados, por lo que incluir columnas no agregadas o condiciones incorrectas contradice su finalidad.

SELECT category, COUNT(product_id) as product_count
FROM products
GROUP BY category
HAVING category = 'Electronics';

Aunque la consulta se ejecuta correctamente, se recomienda utilizar la cláusula WHERE para filtrar columnas no agregadas. Esto cumple con las mejores prácticas y garantiza la claridad de su código SQL.

WHERE vs. HAVING

Pueden producirse errores como resultado de la confusión entre WHERE y HAVING. Para evitarlo, recuerde que WHERE es para filas y HAVING es para grupos.

En la consulta anterior con el error, sería más apropiado utilizar WHERE en lugar de HAVING:

SELECT category, COUNT(product_id) as product_count
FROM products
WHERE category = 'Electronics'
GROUP BY category;

Excluir funciones agregadas de HAVING

Al filtrar basándose en valores agregados, recuerde incluir la función agregada en la cláusula HAVING. En el siguiente ejemplo, product_id debería ser COUNT(product_id) en la cláusula HAVING:

SELECT category, COUNT(product_id)
FROM products
GROUP BY category
HAVING product_id > 5;

Hay muchos más errores posibles de sintaxis SQL. La buena noticia es que, con la práctica, aprenderás rápidamente a evitarlos. Cuando encuentres un error, presta atención al mensaje de error, que puede ayudarte a identificar el problema específico.

¿Listo para Practicar la Cláusula HAVING de SQL?

La cláusula HAVING de SQL es una herramienta valiosa para optimizar los resultados de las consultas en el análisis de datos, los informes y el Business Intelligence. El dominio de esta cláusula permite a los usuarios de SQL extraer información valiosa de los datos agregados.

A medida que avance en su viaje por SQL, no tema cometer errores al escribir consultas con la cláusula HAVING; ¡todo forma parte del proceso de aprendizaje! La buena noticia es que no estás solo. Hay mucho material disponible en LearnSQL.es para ayudarte a dominar la cláusula HAVING. Para más ejemplos, vea nuestro Tutorial SQL HAVING.

Para ir aún más lejos, echa un vistazo a nuestro tema Curso completo de SQL . Abarca todo lo que SQL puede ofrecer, incluida la importantísima cláusula HAVING. Este curso le permite combinar los conocimientos teóricos con la práctica escribiendo sus propias consultas SQL en una consola interactiva y recibiendo comentarios al instante. ¿A qué estás esperando? ¡Póngase manos a la obra!