🙏 Realmente necesitamos su apoyo. Necesitamos financiamiento para continuar nuestra misión: publicar nuevas lecciones y mejorar la plataforma. Si puede, por favor apoye el proyecto con una donación. Ayude al proyecto ahora →
Código SQL copiado al portapapeles

Lesión 4.3 · Tiempo de lectura: ~7 minutos

Al usar GROUP BY con agregados, a menudo necesitas filtrar grupos por sus resultados agregados. HAVING es el operador para filtrar grupos, así como WHERE filtra filas individuales. En esta lección, aprenderás las diferencias entre WHERE y HAVING, la sintaxis y ejemplos prácticos en Sakila. Al final, usarás HAVING con confianza para un análisis de datos profundo.

Filtrado de Grupos con HAVING

En lecciones anteriores, aprendiste GROUP BY para agrupar datos y aplicar agregados. Ahora viene el siguiente paso: filtrar los grupos mismos por condiciones sobre valores agregados.

HAVING hace esto permitiendo condiciones después de la agrupación.

WHERE vs HAVING

  • WHERE filtra filas antes de agrupar
  • HAVING filtra grupos después de la agregación
SELECT column1, COUNT(*) AS cnt
FROM table
WHERE column1 > 100          -- filtrar ANTES de agrupar
GROUP BY column1
HAVING COUNT(*) > 10;        -- filtrar DESPUÉS de agrupar

Sintaxis de HAVING

Estructura básica:

SELECT column1, AGG_FUNCTION(column2)
FROM table
GROUP BY column1
HAVING condition;

La condición en HAVING típicamente involucra una función agregada.


Ejemplos con Condición Única

Clientes con pagos totales superiores a 100

SELECT customer_id, SUM(amount) AS total_paid
FROM payment
GROUP BY customer_id
HAVING SUM(amount) > 100;

Resultado: solo clientes cuyos pagos totales superan 100.

Miembros del personal que procesaron más de 50 pagos

SELECT staff_id, COUNT(*) AS payments_count
FROM payment
GROUP BY staff_id
HAVING COUNT(*) > 50;

Resultado: personal con más de 50 pagos procesados.

Clientes con pago promedio ≥ 5

SELECT customer_id, AVG(amount) AS avg_payment
FROM payment
GROUP BY customer_id
HAVING AVG(amount) >= 5;

Resultado: clientes cuyo pago promedio es al menos 5.


HAVING con Múltiples Condiciones

Puedes combinar condiciones usando AND y OR:

SELECT staff_id, COUNT(*) AS cnt, SUM(amount) AS total
FROM payment
GROUP BY staff_id
HAVING COUNT(*) > 50 AND SUM(amount) > 500;

Resultado: personal con más de 50 pagos Y total superior a 500.

Con operador OR

SELECT customer_id, COUNT(*) AS rentals, SUM(amount) AS paid
FROM payment
GROUP BY customer_id
HAVING COUNT(*) > 100 OR SUM(amount) > 1000;

Resultado: clientes con más de 100 pagos O total superior a 1000.


Ejemplos Prácticos

Categorías de películas con ventas superiores a 2000

SELECT category_id, SUM(p.amount) AS total_sales
FROM payment p
JOIN rental r ON p.rental_id = r.rental_id
JOIN inventory i ON r.inventory_id = i.inventory_id
JOIN film_category fc ON i.film_id = fc.film_id
GROUP BY category_id
HAVING SUM(p.amount) > 2000;

Países con más de 20 clientes

SELECT country, COUNT(*) AS customers_count
FROM customer cu
JOIN address a ON cu.address_id = a.address_id
JOIN city ci ON a.city_id = ci.city_id
JOIN country co ON ci.country_id = co.country_id
GROUP BY country
HAVING COUNT(*) > 20;

Tiendas con ingresos diarios superiores a 500

SELECT store_id, DATE(payment_date) AS pay_date, SUM(amount) AS daily_revenue
FROM payment
GROUP BY store_id, DATE(payment_date)
HAVING SUM(amount) > 500;

Preguntas Frecuentes

¿Por qué no puedo usar WHERE en lugar de HAVING?

WHERE opera antes de agrupar, por lo que no puede verificar funciones agregadas. HAVING opera después de agrupar y puede analizar resultados de agregación (COUNT, SUM, AVG, etc.).

¿Puedo usar una columna no agregada en HAVING?

Sí, puedes usar una columna de GROUP BY, pero generalmente esto no es necesario. Por ejemplo, HAVING customer_id > 100 funciona, pero es más natural escribir esto en WHERE antes de agrupar.

¿Se puede usar HAVING sin GROUP BY?

Técnicamente en algunos SGBD esto es posible, pero es impráctico ya que HAVING está diseñado para filtrar grupos. Usa WHERE para filtrar filas individuales sin agrupar.


Preguntas de Entrevista

¿Qué es HAVING y cómo se diferencia de WHERE?

HAVING filtra grupos después de la agregación, mientras que WHERE filtra filas antes de agrupar. WHERE no puede trabajar con funciones agregadas, pero HAVING solo puede trabajar con ellas.

¿Puedo usar tanto WHERE como HAVING en una consulta?

Sí, esto es incluso recomendable. WHERE filtra filas antes de agrupar, y HAVING filtra grupos después. Por ejemplo, WHERE amount > 10 GROUP BY customer_id HAVING SUM(amount) > 100 primero excluye pagos pequeños, luego agrupa y filtra grupos.

¿Cuál es el orden de ejecución: WHERE o HAVING?

WHERE se aplica primero (antes de GROUP BY), luego GROUP BY realiza la agrupación, luego HAVING filtra los grupos resultantes, y finalmente se aplican ORDER BY y LIMIT.


Puntos clave de esta lección:

  • HAVING filtra grupos después de la agregación, WHERE filtra filas antes de agrupar.
  • HAVING se usa con funciones agregadas (COUNT, SUM, AVG, MIN, MAX).
  • Puedes combinar múltiples condiciones en HAVING usando AND/OR.
  • A menudo WHERE y HAVING trabajan juntos: WHERE excluye filas no deseadas, HAVING filtra grupos.
  • HAVING permite consultas analíticas profundas con filtrado a nivel de grupo.

En la próxima lección, exploraremos ORDER BY para ordenar resultados.