Saltar al contenido principal
eLearner.app
Módulo 3 · Lección 4 de 412/57 en el curso~8 min
Lecciones del módulo (4/4)

Filtrar grupos: HAVING

Una vez que tengas un resultado por grupo (lección anterior), a menudo querrás mantener sólo los grupos que cumplan una condición: departamentos con más de 2 personas, proyectos con un presupuesto promedio superior a 100k, usuarios con al menos 10 pedidos. Para hacer esto WHERE no es suficiente.

¿Por qué DÓNDE no es suficiente?

WHERE filtra las filas de la tabla, antes de la agregación. entonces no puede ver el resultado de COUNT(*) o AVG(...): cuando se ejecuta WHERE, esos Los valores aún no se han calculado.

SQL
-- ERROR: COUNT(*) doesn't exist yet when WHERE is evaluated
SELECT department_id, COUNT(*) AS count
FROM   employees
WHERE  COUNT(*) > 2     -- ❌ doesn't work
GROUP BY department_id;

Para filtrar después de la agregación, hay una cláusula dedicada: HAVING.

La sintaxis

SQL
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM   table
GROUP BY grouping_column
HAVING   condition_on_aggregate;
SQL
-- Departments with more than 2 employees:
SELECT department_id, COUNT(*) AS count
FROM   employees
GROUP BY department_id
HAVING   COUNT(*) > 2;

HAVING es para GROUP BY lo que WHERE es para FROM: la misma idea ("filtro"), pero se aplica después de la agrupación, en conjunto.

El orden lógico de las cláusulas.

Para no volver a confundir WHERE y HAVING, recuerde el orden en el que SQL los ejecuta mentalmente:

  1. FROM / JOIN: crea la tabla inicial uniendo fuentes.
  2. WHERE: elimina las filas que no te interesan.
  3. GROUP BY: reúne las filas restantes en grupos.
  4. HAVING: elimina los grupos que no te interesan.
  5. SELECT: calcula las columnas finales (incluidos los agregados).
  6. ORDER BY / LIMIT: reordenar y cortar.

Notas importantes:

  • en WHERE sólo puedes usar columnas de tabla;
  • en HAVING puedes usar agrupar columnas y agregados.
SQL
-- Classic combo: filter first, group, filter the groups, sort.
SELECT d.name, AVG(e.salary) AS average
FROM   employees   AS e
JOIN   departments AS d ON e.department_id = d.id
WHERE  e.hired_on >= '2018-01-01'   -- filter rows
GROUP BY d.name
HAVING   AVG(e.salary) > 35000      -- filter groups
ORDER BY average DESC;

Pruébalo

Ejercicio#sql.m3.l4.e1
Intentos: 0Cargando...

Para cada departamento, muestre el nombre (departamentos.nombre) y el recuento de empleados, PERO solo para departamentos con al menos 2 empleados. Dos columnas, una fila por departamento calificado.

Cargando editor...
Mostrar pista

La condición 'al menos 2' se convierte en COUNT(*) >= 2 en HAVING.

Solución disponible después de 3 intentos

Ejercicio de revisión

Ejercicio#sql.m3.l4.e2
Intentos: 0Cargando...

Muestre los departamentos (departamentos.nombre) cuyo salario promedio supera los 35000. Considere solo los empleados contratados a partir de 2018. Dos columnas: nombre y promedio. Ordenar por promedio descendente.

Cargando editor...
Mostrar pista

DONDE filtra las filas (empleados contratados a partir de 2018), HAVING filtra los grupos (promedio > 35000).

Solución disponible después de 3 intentos