WHERE filtra filas antes de la agrupación y agregaciones, es decir, determina qué registros entran en la agrupación/agregación. HAVING filtra grupos ya después de aplicar las funciones de agregado.
Ejemplo:
-- Obtener departamentos con salario total superior a 50000, excluyendo empleados despedidos SELECT department, SUM(salary) as total FROM employees WHERE status = 'active' GROUP BY department HAVING SUM(salary) > 50000;
Aquí:
¿Se pueden usar funciones de agregado en WHERE?
Error: se intenta escribir WHERE SUM(amount) > 100, pero no se puede — las funciones de agregado se aplican SOLO en HAVING.
Ejemplo (INCORRECTO):
SELECT customer_id, SUM(amount) FROM orders WHERE SUM(amount) > 100 GROUP BY customer_id -- ERROR: uso incorrecto de SUM() en WHERE
Correcto:
SELECT customer_id, SUM(amount) FROM orders GROUP BY customer_id HAVING SUM(amount) > 100;
Historia
Desarrollo de CRM. Intento de filtrar clientes con más de 5 pedidos a través de WHERE COUNT(order_id) > 5. La consulta no funcionó. Resultado: número de clientes en el informe incorrecto, ya que COUNT no se puede usar en WHERE.
Historia
Análisis de negocio. En lugar de filtrar productos no activos en WHERE utilizaron HAVING. Resultado: agregación de grupos "vacíos" y SQL lento. Corregido trasladando el filtro por estado a WHERE.
Historia
Informe complejo. Usaron HAVING sin GROUP BY para filtrar filas individuales. En algunos SGBD esto provoca un error, en otros, un comportamiento no obvio. Conclusión: HAVING debe ir después de la agrupación y para condiciones de agregado.