La diferencia clave: uno filtra filas y otro grupos

Vamos al lío. La diferencia más importante es esta:

WHERE filtra datos antes de agrupar.

HAVING filtra resultados después de usar GROUP BY.

Esta es la idea que tienes que quedarte. El error típico es intentar usar WHERE para filtrar una función como COUNT() o SUM(), pero en ese momento SQL todavía no ha creado esos grupos.

WHERE: filtrar registros individuales

WHERE trabaja directamente sobre las filas originales de la tabla. Es decir, decide qué datos entran en la consulta antes de hacer cálculos.

SELECT cliente,
importe
FROM ventas
WHERE importe > 500;

Aquí SQL primero revisa todas las ventas y se queda solamente con aquellas cuyo importe supera los 500 euros.

Es perfecto para filtros como:

  • Ventas realizadas en una fecha concreta.
  • Clientes de una ciudad determinada.
  • Productos activos.

HAVING: filtrar grupos creados con GROUP BY

HAVING aparece cuando ya estás agrupando datos. Por ejemplo, si quieres saber qué clientes han gastado más de 5.000 euros en total.

SELECT cliente,
SUM(importe) AS total_compras
FROM ventas
GROUP BY cliente
HAVING SUM(importe) > 5000;

Aquí no estamos filtrando una venta concreta. Estamos filtrando el resultado de sumar todas las ventas de cada cliente.

SQL primero hace el grupo:

  1. Junta todas las ventas del mismo cliente.
  2. Calcula el total con SUM().
  3. Aplica el filtro HAVING.

Ejemplo real de oficina: informe comercial

Imagina que el departamento de ventas quiere ver solo los clientes activos este año que hayan comprado más de 10.000 euros.

Aquí necesitas ambas cláusulas:

SELECT cliente,
SUM(importe) AS ventas_totales
FROM ventas
WHERE fecha >= '2026-01-01'
GROUP BY cliente
HAVING SUM(importe) > 10000;

La lógica es:

  • WHERE elimina ventas antiguas.
  • GROUP BY junta las ventas por cliente.
  • HAVING elimina clientes que no llegan al objetivo.

Por qué no puedes usar WHERE con SUM o COUNT

Este es uno de los errores más frecuentes:

SELECT cliente,
COUNT(*) AS pedidos
FROM pedidos
WHERE COUNT(*) > 5
GROUP BY cliente;

Esta consulta falla porque cuando SQL está aplicando WHERE todavía no existe el resultado de COUNT().

La solución correcta es:

SELECT cliente,
COUNT(*) AS pedidos
FROM pedidos
GROUP BY cliente
HAVING COUNT(*) > 5;

Errores comunes usando WHERE y HAVING

  • Usar HAVING para filtros simples. Funciona en algunos casos, pero es menos eficiente porque primero calcula grupos innecesarios.
  • Intentar filtrar una función agregada con WHERE.
  • Confundir el orden de ejecución de SQL.
  • Poner condiciones de fechas o estados en HAVING cuando deberían ir en WHERE.
  • Crear consultas difíciles de leer mezclando demasiadas condiciones en el mismo bloque.

Un truco mental para no equivocarte

Hazte esta pregunta:

"¿Estoy filtrando una fila concreta o un resultado calculado?"

Si es una fila → WHERE.

Si es un cálculo de grupo → HAVING.

Con esa regla resolverás la mayoría de casos del día a día.

Pro Tip

Cuando una consulta con GROUP BY te dé error, revisa primero si estás intentando usar WHERE con una función agregada. Otro truco útil es escribir primero el SELECT, FROM y WHERE, comprobar que los datos son correctos y después añadir GROUP BY y HAVING al final. En muchos editores SQL puedes usar Ctrl + Shift + Enter para ejecutar bloques completos de consulta.