Vamos a repasar otra vez el orden de ejecución de las operaciones en SQL, y también sobre con qué puede y no puede trabajar WHERE y HAVING. Es un punto importante, sobre el que se construyen muchos matices del trabajo con consultas SQL. Tienes que entenderlo muy bien.
Entonces, ¿en qué se diferencia WHERE de HAVING, cuándo usar uno y cuándo el otro, y cómo se relacionan? Esto te ayudará a no liarte con la lógica de las consultas y a filtrar datos de forma eficiente. Vamos a resumir lo que sabemos sobre WHERE y HAVING.
¿Qué es WHERE?
WHERE es una condición que se usa para filtrar filas antes de la agrupación o de aplicar funciones de agregación. O sea, primero se seleccionan de la tabla las filas que cumplen los criterios, y solo después se hace la agrupación sobre los datos que quedan.
👉 Imagínate que estás recogiendo frutas en el mercado. WHERE es el filtro que te ayuda a descartar las manzanas malas antes de empezar a clasificarlas por tamaño o color.
Ejemplo:
SELECT *
FROM students
WHERE age > 18;
Esta consulta selecciona todos los estudiantes mayores de 18 años antes de hacer cualquier otra operación.
¿Qué es HAVING?
HAVING es un filtro que se aplica después de agrupar los datos (GROUP BY). Permite poner condiciones sobre los datos agrupados, por ejemplo, dejar solo los grupos donde la nota media de los estudiantes es mayor que 80.
👉 Volviendo al ejemplo de las manzanas. HAVING es el filtro que usas después de haberlas clasificado en cestas (grupos). Ahora, por ejemplo, solo te interesan las cestas (grupos) donde hay más de diez manzanas.
Ejemplo:
SELECT cesta, COUNT(*)
FROM manzanas
GROUP BY cesta
HAVING COUNT(*) > 10;
Esta consulta selecciona solo las cestas donde hay más de 10 manzanas.
Diferencias principales:
| Característica | WHERE |
HAVING |
|---|---|---|
| Aplicación | Filtra filas antes de la agrupación | Filtra grupos después de la agrupación |
| Trabajo con agregación | No se pueden usar funciones de agregación | Se pueden usar funciones de agregación |
| Objetivo | Quita filas innecesarias para la agrupación | Quita grupos que no cumplen la condición |
Orden de ejecución de WHERE, GROUP BY y HAVING
Para entender mejor cómo funcionan WHERE y HAVING, vamos a ver el orden de ejecución de las consultas SQL:
- Primero se ejecuta
FROM, se seleccionan las filas de la tabla. - Luego se aplica
WHERE, filtrando solo las filas que cumplen las condiciones. - Después se hace la agrupación con
GROUP BY. Obtenemos una nueva tabla con los datos agrupados. - Se aplica
HAVING, filtrando los grupos que cumplen las condiciones. - Por último, se seleccionan los resultados con
SELECT.
En esquema se ve así:
1. FROM → 2. WHERE → 3. GROUP BY → 4. HAVING → 5. SELECT
Ejemplo:
SELECT department, AVG(age) AS avg_age
FROM students
WHERE age > 18
GROUP BY department
HAVING AVG(age) > 20;
Aquí pasa lo siguiente:
- En la tabla
studentsse seleccionan las filas dondeage > 18(se usaWHERE). - Las filas que quedan se agrupan por
department. - Para cada grupo se calcula la edad media de los estudiantes.
- Los grupos donde la edad media es menor o igual a 20 se excluyen con
HAVING. - Se muestran los resultados.
Ejemplos de uso combinado
Ejemplo 1: Filtrado antes y después de la agrupación
Condición: encontrar las facultades donde hay más de 5 estudiantes, teniendo en cuenta solo los estudiantes mayores de 18 años.
Tabla original students
| id | name | department | age | gpa |
|---|---|---|---|---|
| 1 | Alex Lin | ComputerSci | 20 | 3.8 |
| 2 | Maria Chi | Math | 22 | 3.5 |
| 3 | Anna Song | ComputerSci | 19 | 4.0 |
| 4 | Otto Art | Math | 17 | 3.9 |
| 5 | Liam Park | Physics | 21 | 3.7 |
| 6 | Jane Doe | ComputerSci | 23 | 3.6 |
| 7 | Tom Brown | Math | 25 | 3.4 |
| 8 | Sara White | Math | 19 | 3.8 |
| 9 | John Smith | ComputerSci | 20 | 3.7 |
| 10 | Emily Green | Physics | 18 | 3.9 |
| 11 | Mark Blue | ComputerSci | 21 | 3.5 |
| 12 | Zoe Black | Math | 22 | 3.6 |
| 13 | Max Gray | ComputerSci | 20 | 3.9 |
| 14 | Eva Gold | Math | 23 | 3.7 |
| 15 | Nick Silver | Physics | 19 | 3.8 |
Consulta:
SELECT department, COUNT(*) AS student_count
FROM students
WHERE age > 18
GROUP BY department
HAVING COUNT(*) > 5;
Resultado: -- Resultado de la consulta
| department | student_count |
|---|---|
| ComputerSci | 6 |
Explicación:
- Primero quitamos las filas donde
age <= 18(condiciónWHERE). - Agrupamos los datos por facultad (
GROUP BY department). - Calculamos el número de estudiantes en cada grupo.
- Quitamos los grupos donde hay menos o igual a 5 estudiantes (
HAVING COUNT(*) > 5).
Ejemplo 2: Error al usar WHERE en vez de HAVING
Condición: Encontrar las facultades donde la edad media es mayor de 22 años.
Consulta incorrecta:
SELECT department, AVG(age) AS avg_age
FROM students
WHERE AVG(age) > 22
GROUP BY department;
Error: SQL no permite usar funciones de agregación AVG en WHERE, porque en ese momento los agregados aún no están calculados.
Consulta correcta:
SELECT department, AVG(age) AS avg_age
FROM students
GROUP BY department
HAVING AVG(age) > 22;
Aquí la condición AVG(age) > 22 se aplica después de la agrupación.
Consejos prácticos
Si necesitas filtrar filas, usa WHERE. Ejemplo: Encontrar todos los empleados con salario mayor a 5000.
SELECT *
FROM employees
WHERE salary > 5000;
Si necesitas filtrar grupos, usa HAVING. Ejemplo: Encontrar los departamentos con salario total mayor a 100 000.
SELECT department, SUM(salary) AS total_salary
FROM employees
GROUP BY department
HAVING SUM(salary) > 100000;
Combina WHERE y HAVING para condiciones más complejas.
Ejemplo: Encontrar países con más de 10 millones de habitantes, teniendo en cuenta solo las ciudades con población mayor a 1 millón.
SELECT country, SUM(population) AS total_population
FROM cities
WHERE population > 1000000
GROUP BY country
HAVING SUM(population) > 10000000;
Errores típicos y cómo solucionarlos
Uno de los errores más comunes es confundir WHERE y HAVING. Por ejemplo, intentar usar una función de agregación en WHERE:
SELECT department, COUNT(*)
FROM students
WHERE COUNT(*) > 10
GROUP BY department;
Esta consulta dará error, porque los cálculos de agregación no están disponibles en la etapa de WHERE. La forma correcta es usar HAVING:
SELECT department, COUNT(*)
FROM students
GROUP BY department
HAVING COUNT(*) > 10;
Otro error es elegir condiciones incorrectas para WHERE. Por ejemplo:
SELECT department, AVG(age) AS avg_age
FROM students
WHERE avg_age > 20
GROUP BY department;
Aquí la condición avg_age > 20 es incorrecta, porque avg_age aún no está calculado. La solución es mover esa condición a HAVING:
SELECT department, AVG(age) AS avg_age
FROM students
GROUP BY department
HAVING AVG(age) > 20;
Espero que ahora tengas claro en qué se diferencian WHERE y HAVING, cómo usarlos bien y cómo evitar los errores típicos. Este conocimiento te va a servir para crear informes complejos, filtrar datos para análisis y optimizar consultas. O sea, para la mayoría de las consultas SQL reales que vas a escribir :)
GO TO FULL VERSION