Contenido de esta guía
Respuesta rápida
WHERE filtra filas antes de GROUP BY. HAVING filtra grupos después de calcular agregaciones.
Una consulta puede usar las dos cláusulas cuando necesita limitar primero los datos de entrada y después conservar solo los grupos que cumplen un resumen.
Piensa en dos preguntas diferentes
- WHERE: ¿qué filas individuales participan?
- HAVING: ¿qué grupos calculados permanecen?
Esta distinción es más fiable que memorizar qué palabras “van” con cada cláusula. Identifica primero si la condición puede evaluarse sobre una fila o necesita conocer un total, una media, un máximo u otra agregación.
| Aspecto | WHERE | HAVING |
|---|---|---|
| Unidad que filtra | Filas | Grupos |
| Momento lógico | Antes de agrupar | Después de agrupar |
| Condición típica | activo = 1 | COUNT(*) >= 2 |
| Efecto | Cambia las filas que alimentan el cálculo | Oculta grupos ya calculados |
Ejemplo paso a paso
SELECT ciudad,
COUNT(*) AS clientes_activos
FROM clientes
WHERE activo = 1
GROUP BY ciudad
HAVING COUNT(*) >= 2
ORDER BY clientes_activos DESC, ciudad;WHERE activo = 1retira las filas inactivas.GROUP BY ciudadreúne las filas restantes por ciudad.COUNT(*)calcula cuántos clientes activos tiene cada grupo.HAVING COUNT(*) >= 2conserva solo ciudades con dos o más.
| ciudad | clientes_activos |
|---|---|
| Madrid | 3 |
| Bilbao | 2 |
| Sevilla | 2 |
| Valencia | 2 |
Cómo decidir cláusula por cláusula
- Escribe la condición en lenguaje natural.
- Pregunta si puede resolverse mirando una sola fila.
- Si la respuesta es sí, empieza por
WHERE. - Si necesita un cálculo del grupo, utiliza
HAVING. - Cuando existan ambas necesidades, aplica primero
WHEREy despuésHAVING.
Errores frecuentes
Intentar usar una agregación en WHERE
SELECT ciudad, COUNT(*)
FROM clientes
WHERE COUNT(*) >= 2
GROUP BY ciudad;COUNT(*) todavía no existe en el momento lógico de WHERE. Esa condición pertenece a HAVING.
Usar HAVING para una condición de fila
Algunos motores aceptan extensiones, pero filtrar antes con WHERE expresa mejor la intención y evita agrupar filas que no deberían participar.
Olvidar que WHERE cambia el cálculo
Excluir pedidos cancelados antes de sumar produce un total distinto de sumar todos los pedidos y filtrar grupos después.
Práctica guiada
Clientes activos por ciudad
Devuelve las ciudades con al menos dos clientes activos. Muestra la ciudad y el conteo, ordenando primero por el conteo descendente y después por ciudad.
activo = 1 se comprueba en cada fila.ciudad.COUNT(*).Solución razonada
SELECT ciudad,
COUNT(*) AS clientes_activos
FROM clientes
WHERE activo = 1
GROUP BY ciudad
HAVING COUNT(*) >= 2
ORDER BY clientes_activos DESC, ciudad;WHERE limita las filas de entrada. HAVING compara el conteo ya calculado de cada ciudad.
Compatibilidad y extensiones
La separación conceptual entre filtros de fila y de grupo es portable. Algunos motores permiten que HAVING haga referencia a alias o se use en situaciones adicionales. Para una ruta inicial clara, escribe las condiciones de fila en WHERE y reserva HAVING para condiciones que dependen del grupo.
Qué debes recordar
WHEREreduce las filas antes de agrupar.HAVINGreduce grupos después de agregar.- Una consulta puede y suele necesitar ambas.
- Colocar un filtro en otra fase puede cambiar el resultado.
Conceptos relacionados
Fuentes técnicas consultadas
- PostgreSQL: WHERE, GROUP BY y HAVING
- MySQL 8.4: SELECT y HAVING
- SQLite: generación del resultado SELECT
Para situar ambos filtros en la consulta completa, consulta el orden de ejecución de SQL paso a paso.