HAVING filtra grupos. Se escribe después de GROUP BY y permite quedarse solo con los grupos que cumplen una condición sobre una función agregada: los clientes con más de un pedido, los productos que suman más de 1.000 €, etc.
SELECT columnas, funcionAgregada(columna)
FROM tabla
WHERE condicionSobreFilas
GROUP BY columnas
HAVING condicionSobreGrupos;
HAVING frente a WHERE
Las dos filtran, pero en momentos distintos de la consulta:
| Cláusula | Qué filtra | Cuándo se aplica | ¿Admite funciones agregadas? |
|---|---|---|---|
WHERE |
Filas | Antes de agrupar | No |
HAVING |
Grupos | Después de agrupar | Sí |
Por eso esta consulta falla: cuando se evalúa el WHERE, todavía no existen los grupos y COUNT(*) no tiene sentido.
WHERE. SQL Server lo indica con un mensaje parecido a: Un agregado no puede aparecer en la cláusula WHERE a menos que esté en una subconsulta contenida en una cláusula HAVING.Ejemplo básico
La forma correcta de obtener los clientes con más de un pedido es mover la condición a HAVING:
| idClientes | pedidos |
|---|---|
| 2 | 2 |
| 4 | 2 |
Solo María (idClientes = 2) y Luis (idClientes = 4) han hecho más de un pedido.
HAVING con SUM
Cualquier función agregada vale. Aquí, los clientes cuyo gasto total supera los 3.000 €, unidos a la tabla Clientes para ver su nombre:
| nombre | apellidos | gastoTotal |
|---|---|---|
| Luis | Sanchez García | 4999,00 |
| Ana | Fernandez Montero | 4304,25 |
| María | Lopez ruiz | 3199,78 |
WHERE y HAVING en la misma consulta
Lo habitual es combinarlas: WHERE descarta filas antes de agrupar y HAVING descarta grupos después. Esta consulta cuenta, por descripción de producto, cuántos pedidos se hicieron a partir de julio de 2022, y se queda solo con las descripciones que tienen al menos dos:
| descripcionProducto | pedidos | unidades |
|---|---|---|
| Altavoz Alexa | 2 | 100 |
El orden en que el motor procesa una consulta ayuda a entenderlo:
FROMyJOIN: qué tablas intervienen.WHERE: qué filas se quedan.GROUP BY: cómo se agrupan.HAVING: qué grupos se quedan.SELECT: qué columnas se devuelven.ORDER BY: en qué orden.
WHERE aunque también funcione en HAVING: el motor descarta las filas antes de agrupar y la consulta hace menos trabajo.Errores frecuentes
- Usar un alias del
SELECTen elHAVING.HAVING pedidos > 1funciona en algunos motores, como MySQL, pero no en SQL Server, porqueHAVINGse evalúa antes que elSELECT. Repite la expresión:HAVING COUNT(*) > 1. - Olvidar el
GROUP BY. Sin él, toda la tabla es un único grupo yHAVINGdevuelve una fila o ninguna. - Filtrar por una columna que no está agrupada. En
HAVINGsolo pueden aparecer columnas delGROUP BYo funciones agregadas.
Practica
Modifica los ejemplos de arriba para responder a estas preguntas:
- ¿Qué clientes han comprado más de 50 unidades en total? (Pista:
SUM(numeroProductos).) - ¿Qué descripciones de producto tienen un precio medio superior a 400 €?
- ¿Qué pasa si en el último ejemplo cambias
>= 2por>= 1?