Saltar al contenido principal

Diferencia entre WHERE y HAVING en SQL

Descubre cómo WHERE filtra los datos a nivel de fila en las consultas SQL, mientras que HAVING filtra los datos agrupados tras la agregación, y domina sus distintos usos en las consultas SQL.
Actualizado 10 oct 2024  · 8 min de lectura

WHERE y HAVING son dos cláusulas esenciales en SQL. Tanto si escribes consultas superavanzadas como si son muy sencillas, te encontrarás con la necesidad de utilizar ambas. Puedes pensar en WHERE y HAVING como hermanos. Ambos cumplen una función similar (filtrar), y a menudo aparecen juntos. Pero, al igual que los hermanos, tienen características distintas y papeles únicos. 

Si estás en proceso de clasificar WHERE y HAVING, te sugiero que te inscribas en nuestro curso de habilidades SQL Fundamentals como punto de partida excelente y completo. Te enseñará las diferentes cláusulas SQL, el orden de ejecución SQL, la optimización de las consultas SQL y muchas otras cosas fundamentales.  

La respuesta breve: DÓNDE vs. TENIENDO 

La respuesta breve y fuente de confusión para mucha gente es que WHERE trabaja con datos a nivel de fila, mientras que HAVING opera con datos agrupados. He aquí una pauta:

  • WHERE filtra las filas antes de que se produzca cualquier agrupación o agregación. Se aplica a filas individuales y no puede utilizarse con funciones agregadas.

  • HAVING filtra los grupos después de haber realizado la agrupación y la agregación. Se aplica a los resultados de las funciones agregadas y se utiliza en combinación con GROUP BY.

Un ejemplo rápido para mostrar la diferencia 

Veamos un ejemplo rápido. Si quieres seguir tu propio flujo de trabajo, puedes descargar el conjunto de datos de alquiler de propiedades de este repositorio de GitHub.

Ahora, supongamos que necesitamos devolver todas las propiedades de nuestro conjunto de datos que tengan un precio de alquiler inferior a 500 $. El nivel de detalle de cada fila del conjunto de datos (una propiedad por fila) coincide con el nivel de detalle de la condición de la consulta. Por lo tanto, utilizamos WHERE en la siguiente consulta:

SELECT *
FROM rentals
WHERE rental_price < 500

El resultado sería el siguiente. Observa que se devuelven 118 filas.

Filtrado simple de filas con SQL WHERE

Filtrado simple de filas con WHERE. Imagen del autor.

Ahora, supongamos que no queremos tener una tabla de inmuebles, sino de ciudades que tienen un precio medio de alquiler inferior a 2.700 $. En lugar de que cada fila corresponda a un inmueble, agruparemos las filas y agregaremos el precio de alquiler en un precio medio de alquiler para cada ciudad. Por lo tanto, utilizaremos HAVING, como en esta consulta:

SELECT city, AVG(rental_price) AS average_rent
FROM rentals
GROUP BY city
HAVING AVG(rental_price) < 2700;

Y el resultado sería Observa que sólo hay un resultado. 

Filtrado simple de grupos con HAVING de SQL

Filtrado simple de grupos con HAVING. Imagen del autor.

WHERE, HAVING y orden de ejecución SQL

Vemos que WHERE funciona con filtrado a nivel de filas, mientras que HAVING funciona con filtrado a nivel de agregados. Comprender esta diferencia también nos allana el camino para conocer el orden de ejecución de las cláusulas de SQL.

WHERE se evalúa antes de GROUP BY, y justo después de FROM (y JOIN si está presente); no puede ocuparse de ninguna agrupación o agregación. WHERE entra en juego antes de que se realice ninguna agregación. Por eso sólo funciona con datos a nivel de fila. 

Por su parte, HAVING viene después de ejecutar la cláusula GROUP BY. Eso significa que entra en juego después de transformar la tabla y agruparla a un nivel distinto del nivel de granularidad de la tabla de origen. HAVING opera sobre la nueva versión transformada de la tabla. 

Cómo utilizar la cláusula WHERE en SQL

Demos un paso atrás y analicemos cada cláusula por separado. Podemos empezar con la cláusula WHERE.

Sintaxis y sentencias WHERE

WHERE puede utilizarse en tres sentencias SQL diferentes: SELECT, UPDATE, y DELETE.

WHERE en sentencias SELECT

En las sentencias SELECT, que son las que se utilizan para obtener datos de la base de datos, WHERE desempeña su papel directo en el filtrado a nivel de filas y tiene su lugar bien conocido justo después de la cláusula FROM, como podemos ver en la siguiente consulta:

SELECT column1, column2… etc.
FROM table_name
WHERE condition;

WHERE utilizado con SELECT es el lugar donde la cláusula WHERE se confunde más a menudo con HAVING

WHERE en las sentencias UPDATE

Además, WHERE desempeña un papel importante en las sentencias UPDATE para señalar la fila en la que debe producirse la actualización de los datos, como podemos ver con la siguiente sintaxis:

UPDATE table_name
SET column_name1 = value1, column_name2 = value2… etc.
WHERE condition;

WHERE en las sentencias DELETE

WHERE también es un complemento útil de las sentencias DELETE para señalar los registros (filas) que deben eliminarse, como podemos ver aquí:

DELETE FROM table_name
WHERE condition;

Cómo escribir condiciones WHERE

WHERE se escriben como una simple expresión lógica. Consta de tres partes: la variable/operando, la condición y el valor/resultado. Echemos un vistazo a las opciones de las condiciones de WHERE, que incluyen operadores de comparación y lógicos.  

Signo de operador Descripción Tipo de datos del operando
= Igual a (en la fecha) Numérico, Texto, Fecha/hora, Booleano
< Menos de (antes de la fecha) Numérico, Fecha/hora
> Mayor que (después de la fecha) Numérico, Fecha/hora
<= Inferior o igual a (en la fecha o antes) Numérico, Fecha/hora
>= Mayor o igual que (en o después de la fecha) Numérico, Fecha/hora
<> (!=) No igual a (no en la fecha) Numérico, Texto, Fecha/hora, Booleano
IN Igual a más de un valor (en varias fechas) Numérico, Texto, Fecha/hora, Booleano (¡sin sentido!)
COMO Coincide con un patrón de texto (utilizando comodines) Texto
ENTRE Existe en una gama Numérico, Fecha/hora
Y Combina varias condiciones, todas deben ser verdaderas Lógico (booleano)
O Combina varias condiciones, al menos una debe ser verdadera Lógico (booleano)
NO Niega una condición Lógico (booleano)
IS NULL Comprueba si hay valores nulos Todos los tipos de datos
NO ES NULO Comprueba los valores no nulos Todos los tipos de datos

He aquí un ejemplo en el que utilizamos NOT junto con el operador de comparación IN:

SELECT *
FROM rentals
WHERE city NOT IN ('Cairo', 'Giza');

La declaración devolverá todas las propiedades que no se encuentren ni en las ciudades de El Cairo ni de Guiza.

Utilizar NOT con WHERE

Propiedades fuera de El Cairo y Giza. Imagen del autor.

Casos de uso WHERE

Sabiendo que WHERE opera con las sentencias SELECT, UPDATE y DELETE, podemos prever que puede utilizarse para tres casos de uso: filtrado a nivel de fila, recuperación de datos y manipulación de datos.

Filtrado por filas

Podemos filtrar las filas de nuestra tabla basándonos en una o varias condiciones. La siguiente consulta filtra las filas para incluir sólo las propiedades de la villa.

SELECT *
FROM rentals
WHERE type = ‘villa’;

Utilizar NOT con WHERE

Seleccionar propiedades de la villa. Imagen del autor.

Data retrieval

WHERE se puede utilizar para recuperar un punto de datos concreto que estemos buscando. Es similar al filtrado por filas, pero más específico. Suponiendo que necesitemos conocer el ID de la vivienda que estaba disponible el 1 de enero de 2022 en El Cairo, podemos utilizar la siguiente consulta:

SELECT property_id
FROM rentals
WHERE available_date = '2022-01-01'
AND city = 'Cairo';

Filtrado por filas con WHERE

Recuperar un punto de datos. Imagen del autor.

Manipulación de datos

Por último, WHERE es una gran ayuda para modificar valores y eliminar registros concretos de tu base de datos. Por ejemplo, suponiendo que descubrimos que la propiedad 171 en realidad no admite mascotas, podemos modificar la columna pet_friendly utilizando WHERE en una declaración UPDATE de la siguiente manera:

UPDATE rentals
SET pet_friendly = false
WHERE property_id = 171;

Cómo utilizar la cláusula HAVING en SQL

Ahora, es el momento de pasar a la cláusula HAVING con el mismo nivel de detalle. 

Sintaxis y sentencias HAVING

En primer lugar, debemos saber que la cláusula HAVING sólo puede utilizarse en las declaraciones SELECT. Por tanto, la única sintaxis que puede tener es la siguiente:

SELECT grouped_column, aggregate_function(aggregated_column)… etc.
FROM table_name
GROUP BY grouped_column
HAVING condition

Ten en cuenta que puedes añadir más de una columna agrupada y más de una columna agregada. Veremos ejemplos a continuación.

Cómo escribir condiciones HAVING

Al igual que WHERE, las condiciones de HAVING se escriben como expresiones lógicas, pero con un componente adicional, la función de agregación. Así, una condición HAVING consta de 1) función agregada, 2) variable/operando, 3) operador de comparación y 4) valor/resultado.

Funciones agregadas con HAVING

SQL tiene principalmente cinco funciones de agregado, más una sexta que es un caso especial. Estas funciones son:

Función agregada Tipo de datos adecuado
SUMA() Numérico
AVG() Numérico
MIN() Numérico, Texto, Fecha/hora
MAX() Numérico, Texto, Fecha/hora
CONTAR() Numérico, Texto, Fecha/hora, Booleano

Pongamos un ejemplo. Aquí, utilizamos la función COUNT() con GROUP BY para crear una tabla de frecuencias, y utilizamos la condición HAVING como filtro. Concretamente, necesitamos conocer las ciudades que se mencionan 150 veces o menos, lo que en este contexto tendría que ver con el número de inscripciones. Podemos utilizar esta consulta:

SELECT city, COUNT(*) AS properties_count
FROM rentals
GROUP BY city
HAVING COUNT(*) <= 150;

Utilizar MAX() con HAVING

Utilizar COUNT() con HAVING. Imagen del autor.

Comparación y operadores lógicos

HAVING acepta todos los operadores de comparación y lógicos que acepta WHERE. La única diferencia es que el tipo de datos adecuado con HAVING depende sobre todo de la función de agregado, como podemos ver en la tabla anterior.

Casos prácticos HAVING

A diferencia de WHERE, HAVING no se puede utilizar en las declaraciones UPDATE y DELETE; HAVING sólo se utiliza para recuperar datos. A grandes rasgos, esto se traduce en dos escenarios:

Filtrado a nivel de grupo

Este es el uso común y normal de HAVING. Un ejemplo es devolver sólo las ciudades que tienen precios medios de alquiler inferiores a 2.700 $.

SELECT city, AVG(rental_price) AS avg_price
FROM rentals
GROUP BY city
HAVING AVG(rental_price) < 2700;

Filtrado de una fila

Éste es un caso poco común, pero HAVING puede utilizarse para devolver una agregación de una sola fila, como una métrica o un KPI, sólo si cumple una determinada condición. Esto puede conseguirse mediante el uso de HAVING sin GROUP BY. En el ejemplo siguiente, devolvemos el precio medio del alquiler sólo si es inferior a 2.800 $. Si la medida cumple la condición, tendríamos un resultado de una sola fila. Si no, tendríamos una mesa vacía.

SELECT AVG(rental_price) as avg_price
FROM rentals
HAVING AVG(rental_price) > 2800;

Combinar WHERE y HAVING

WHERE y HAVING pueden combinarse para filtrar tablas tanto antes como después de la agregación. En el siguiente ejemplo, devolvemos el recuento de propiedades en cada ciudad, contando sólo las propiedades que admiten mascotas, y filtrando a sólo las ciudades que tienen más de 80 propiedades.

SELECT city, COUNT(*) AS number_properties
FROM rentals
WHERE pet_friendly = true
GROUP BY city
HAVING COUNT(*) > 80;

Combinar WHERE con HAVING

Combinación básica de WHERE y HAVING. Imagen del autor.

La diferencia entre DÓNDE y TENER en el rendimiento

Sabemos que la cláusula WHERE se aplica antes de la agrupación o agregación. Pero también debemos saber que, por esta razón, porque reduce el número de filas procesadas al principio de la consulta, WHERE es más eficaz para filtrar filas individuales. 

Sabemos, por otra parte, que la cláusula HAVING se aplica después de la agregación y filtra el conjunto de resultados basándose en los datos agrupados. Por esta razón, como procesa los datos después de haber agrupado todas las filas, suele ser menos eficaz que WHERE, aunque sigue siendo necesario para las condiciones que implican funciones agregadas.

Veamos esta consulta:

SELECT city, COUNT(*)
FROM rentals
GROUP BY city
HAVING rental_price < 2700;

Esta consulta es ineficaz porque la condición rental_price no depende de ninguna agregación: filtra filas individuales. Esta consulta agrupará primero todos los alquileres por ciudad, los contará y luego filtrará el resultado, lo que es ineficaz porque procesa filas innecesarias. Por esta razón, ésta habría sido una consulta más rápida:

SELECT city, COUNT(*)
FROM rentals
WHERE rental_price < 2700
GROUP BY city;

Consejos de optimización WHERE y HAVING

Basándonos en lo anterior, podemos ver algunas de las buenas prácticas que pueden optimizar nuestro uso de las cláusulas WHERE y HAVING. Esto es importante si tienes grandes conjuntos de datos.

  1. Sé muy selectivo: Filtra según los valores a los que necesites filtrar y nada más. Esto ayudará a reducir el número de filas de la vista y, por tanto, mejorará la eficacia de la consulta.

  2. Sé sencillo: Elimina las condiciones, agregaciones y elaboraciones de tipo innecesarias. Definitivamente, todos estos extras tienen un precio computacional.

  3. Filtra pronto: Si estás haciendo una agregación a nivel de grupo, filtra previamente las filas con WHERE para que el proceso de agrupación sea más rápido. Al hacerlo, estarías reduciendo el número de filas que hay que procesar en la agrupación.

Tabla comparativa

Resumamos nuestras ideas en una tabla práctica:

Comparison DONDE TENIENDO
Objetivo principal Filtrado por filas Filtrado a nivel de grupo
Sintaxis básica SELECCIONA columna1, columna2... FROM nombre_tabla WHERE condición; SELECCIONA columna_agrupada, función_agrupada(columna_agrupada)... FROM nombre_tabla GROUP BY columna_agrupada HAVING condición;
Orden de evaluación Antes de GROUP BY Después de GROUP BY
Declaraciones compatibles SELECCIONAR, ACTUALIZAR, ELIMINAR  SELECCIONA
Condiciones No se pueden incluir funciones agregadas Debe incluir funciones agregadas
Casos prácticos Filtrado por filas Recuperación de datos Manipulación de datos Filtrado a nivel de grupo Filtrado de una fila
Subqueries Puede trabajar con subconsultas Deben escribirse como CTEs

Conclusión

A lo largo del artículo, hemos explorado la principal diferencia entre WHERE y HAVING en SQL, que consiste en que la cláusula WHERE filtra las filas antes de la agregación, mientras que la cláusula HAVING filtra los datos agrupados después de la agregación. También exploramos algunas de las diferencias menos conocidas, como el hecho de que WHERE puede funcionar con las declaraciones SELECT, UPDATE y DELETE, pero HAVING sólo funciona con SELECT. También hablamos un poco sobre el rendimiento.

La hoja de trucos de los fundamentos de SQL de DataCamp proporciona un buen resumen de las cláusulas WHERE y HAVING, y algunas orientaciones sobre cómo realizar filtrados en SQL. Además, si te estás iniciando en SQL, te interesará echar un vistazo al itinerario profesional Fundamentos de SQL y al itinerario profesional Analista de Datos Asociado en SQL


Islam Salahuddin's photo
Author
Islam Salahuddin

Islam es analista de datos, facilitador en el Instituto KPI y profesor en la Universidad de El Cairo. Con formación periodística, Islam tiene intereses diversos, como la escritura, la filosofía, los medios de comunicación, la tecnología y la cultura.

Preguntas frecuentes

¿Cuál es la diferencia entre DONDE y TENER?

WHERE realiza el filtrado a nivel de fila, mientras que HAVING lo hace a nivel de grupo.

¿Puedo combinar WHERE y HAVING en una consulta?

Sí, y es muy recomendable utilizar WHERE si vas a utilizar HAVING.

¿Puede WHERE funcionar con funciones agregadas como HAVING?

No, sólo HAVING puede trabajar con funciones agregadas.

¿Funcionan WHERE y HAVING con los mismos operadores lógicos y de comparación?

Sí, ambos funcionan con los mismos operadores, ya que las condiciones WHERE y HAVING se escriben como expresiones lógicas.

¿Puedo utilizar HAVING sin GROUP BY?

HAVING se utiliza generalmente después de la agrupación con GROUP BY. La única excepción es el filtrado de vistas de un solo valor (como calcular una métrica).

Temas

Aprende SQL con DataCamp

curso

Introduction to SQL

2 hr
1M
Learn how to create and query relational databases using SQL in just two hours.
Ver detallesRight Arrow
Comienza el curso
Ver másRight Arrow
Relacionado

tutorial

Cómo utilizar GROUP BY y HAVING en SQL

Una guía intuitiva para descubrir los dos comandos SQL más populares para agregar filas de tu conjunto de datos
Eugenia Anello's photo

Eugenia Anello

6 min

tutorial

Cómo utilizar un alias SQL para simplificar tus consultas

Explora cómo el uso de un alias SQL simplifica tanto los nombres de las columnas como los de las tablas. Aprende por qué utilizar un alias SQL es clave para mejorar la legibilidad y gestionar uniones complejas.
Allan Ouko's photo

Allan Ouko

9 min

tutorial

Tutorial de comparación de patrones SQL LIKE

Utiliza LIKE para filtrar registros SQL según coincidencias de cadenas específicas. Este tutorial te enseña a utilizar comodines, NOT, LOWER, UPPER y CASE WHEN con LIKE.
Travis Tang 's photo

Travis Tang

8 min

tutorial

CALIFICAR: La sentencia de filtrado SQL que nunca supo que necesitaba

Conozca la cláusula SQL QUALIFY, un método de filtrado esencial aunque poco conocido en SQL. Comprender su sintaxis, usos y en qué se diferencia de otros métodos de filtrado SQL.
Kurtis Pykes 's photo

Kurtis Pykes

8 min

tutorial

Ejemplos y tutoriales de consultas SQL

Si quiere iniciarse en SQL, nosotros le ayudamos. En este tutorial de SQL, le presentaremos las consultas SQL, una potente herramienta que nos permite trabajar con los datos almacenados en una base de datos. Verá cómo escribir consultas SQL, aprenderá sobre
Sejal Jaiswal's photo

Sejal Jaiswal

21 min

tutorial

FUNCIÓN SQL COUNT()

COUNT() te permite contar el número de filas que cumplen determinadas condiciones. Aprende a utilizarlo en este tutorial.
Travis Tang 's photo

Travis Tang

3 min

Ver másVer más