Pular para o conteúdo principal

A diferença entre WHERE e HAVING no SQL

Descubra como o WHERE filtra dados em nível de linha em consultas SQL, enquanto o HAVING filtra dados agrupados após a agregação, e domine seus usos distintos em consultas SQL.
Actualizado 10 de out. de 2024  · 8 min de leitura

WHERE e HAVING são duas cláusulas essenciais no SQL. Quer esteja escrevendo consultas superavançadas ou muito simples, você precisará usar ambos. Você pode pensar em WHERE e HAVING como irmãos. Ambos têm uma função semelhante (filtragem) e geralmente aparecem juntos. Mas, assim como os irmãos, eles têm características distintas e funções exclusivas. 

Se você estiver no processo de classificar WHERE e HAVING, sugiro que se inscreva em nosso curso de habilidades SQL Fundamentals como um ponto de partida excelente e abrangente. Ele ensinará a você sobre as diferentes cláusulas SQL, a ordem de execução do SQL, a otimização de consultas SQL e muitas outras coisas importantes.  

A resposta curta: ONDE vs. TENDO 

A resposta curta e a fonte de confusão para muitas pessoas é que WHERE trabalha com dados em nível de linha, enquanto HAVING opera com dados agrupados. Aqui está uma diretriz:

  • WHERE filtra as linhas antes que ocorra qualquer agrupamento ou agregação. Ela se aplica a linhas individuais e não pode ser usada com funções agregadas.

  • HAVING filtra grupos após o agrupamento e a agregação terem sido realizados. Aplica-se aos resultados de funções agregadas e é usado em conjunto com GROUP BY.

Um exemplo rápido para mostrar a diferença 

Vamos dar uma olhada em um exemplo rápido. Se quiser acompanhar seu próprio fluxo de trabalho, você pode fazer o download do conjunto de dados de aluguéis de imóveis neste repositório do GitHub.

Agora, suponha que precisemos retornar todas as propriedades em nosso conjunto de dados que tenham um preço de aluguel inferior a US$ 500. O nível de detalhe de cada linha do conjunto de dados (uma propriedade por linha) corresponde ao nível de detalhe da condição de consulta. Portanto, usamos WHERE na consulta a seguir:

SELECT *
FROM rentals
WHERE rental_price < 500

O resultado seria o seguinte. Observe que há 118 linhas que são retornadas.

Filtragem simples de linhas com o SQL WHERE

Filtragem simples de linhas com WHERE. Imagem do autor.

Agora, suponha que não queiramos ter uma tabela de propriedades, mas de cidades que tenham um preço médio de aluguel inferior a US$ 2.700. Em vez de cada linha corresponder a uma propriedade, agruparemos as linhas e agregaremos o preço do aluguel em um preço médio de aluguel para cada cidade. Portanto, usaremos HAVING, como nesta consulta:

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

E o resultado seria. Observe que há apenas um resultado. 

Filtragem simples de grupos com SQL HAVING

Filtragem de grupo simples com HAVING. Imagem do autor.

WHERE, HAVING e ordem de execução do SQL

Vemos que WHERE funciona com filtragem em nível de linha, enquanto HAVING funciona com filtragem em nível de agregado. A compreensão dessa diferença também abre caminho para que você aprenda sobre a ordem de execução das cláusulas do SQL.

WHERE é avaliado antes de GROUP BY e logo após FROM (e JOIN, se houver); ele não pode lidar com nenhum agrupamento ou agregação. WHERE entra em ação antes que qualquer agregação seja feita. É por isso que ele opera somente em dados no nível da linha. 

Enquanto isso, HAVING vem após a execução da cláusula GROUP BY. Isso significa que ele entra em ação depois de transformar a tabela e agrupá-la em um nível diferente do nível de granularidade da tabela de origem. HAVING opera na nova versão transformada da tabela. 

Como usar a cláusula WHERE no SQL

Vamos dar um passo atrás e dar uma olhada em cada cláusula por si só. Podemos começar com a cláusula WHERE.

Sintaxe e declarações WHERE

WHERE pode ser usado em três instruções SQL diferentes: SELECT, UPDATE, e DELETE.

WHERE em instruções SELECT

Nas instruções SELECT, que são as instruções usadas para buscar dados do banco de dados, WHERE desempenha seu papel direto na filtragem em nível de linha e tem seu lugar bem conhecido logo após a cláusula FROM, como podemos ver na consulta a seguir:

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

WHERE usado com SELECT é o local onde a cláusula WHERE é mais frequentemente confundida com HAVING

WHERE em instruções UPDATE

Além disso, o site WHERE desempenha um papel importante nos comandos UPDATE para identificar a linha em que a atualização de dados deve ocorrer, como podemos ver na sintaxe a seguir:

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

WHERE em instruções DELETE

WHERE também é uma adição útil aos comandos DELETE para identificar os registros (linhas) que devem ser excluídos, como podemos ver aqui:

DELETE FROM table_name
WHERE condition;

Como escrever condições WHERE

WHERE As condições são escritas como uma expressão lógica simples. Ele consiste em três partes: a variável/operando, a condição e o valor/resultado. Vamos dar uma olhada nas opções das condições do WHERE, que incluem operadores lógicos e de comparação.  

Sinal do operador Descrição Tipo de dados do operando
= Igual a (na data) Numérico, texto, data/carimbo de data/hora, booleano
< Menos de (antes da data) Numérico, data/carimbo de data/hora
> Maior que (após a data) Numérico, data/carimbo de data/hora
<= Menor ou igual a (na data ou antes dela) Numérico, data/carimbo de data/hora
>= Maior ou igual a (na data ou após a data) Numérico, data/carimbo de data/hora
<> (!=) Não igual a (não na data) Numérico, texto, data/carimbo de data/hora, booleano
IN Igual a mais de um valor (em várias datas) Numérico, texto, data/carimbo de data/hora, booleano (mas sem sentido!)
LIKE Corresponde ao padrão de texto (usando curingas) Texto
ENTRE Existe em um intervalo Numérico, data/carimbo de data/hora
E Combina várias condições, todas devem ser verdadeiras Lógico (booleano)
OU Combina várias condições, pelo menos uma deve ser verdadeira Lógico (booleano)
NÃO Nega uma condição Lógico (booleano)
É NULO Verifica se há valores nulos Todos os tipos de dados
IS NOT NULL Verifica se há valores não nulos Todos os tipos de dados

Aqui está um exemplo em que usamos o NOT junto com o operador de comparação IN:

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

A declaração retornará todas as propriedades que não estão nas cidades do Cairo ou de Gizé.

Usando NOT com WHERE

Propriedades fora do Cairo e de Gizé. Imagem do autor.

ONDE casos de uso

Sabendo que WHERE opera com as instruções SELECT, UPDATE e DELETE, podemos prever que ele pode ser usado em três casos de uso: filtragem em nível de linha, recuperação de dados e manipulação de dados.

Filtragem em nível de linha

Podemos filtrar as linhas da tabela com base em uma ou mais condições. A consulta a seguir filtra as linhas para que você inclua apenas as propriedades da villa.

SELECT *
FROM rentals
WHERE type = ‘villa’;

Usando NOT com WHERE

Seleção de propriedades de vilas. Imagem do autor.

Recuperação de dados

WHERE pode ser usado para recuperar um ponto de dados específico que estamos procurando. Isso é semelhante à filtragem em nível de linha, mas é mais específico. Supondo que precisamos saber o ID da propriedade que estava disponível no dia primeiro de janeiro de 2022 no Cairo, podemos usar a seguinte consulta:

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

Filtragem em nível de linha com WHERE

Recuperação de um ponto de dados. Imagem do autor.

Manipulação de dados

Por fim, o site WHERE é um ótimo auxiliar para modificar valores e excluir registros específicos no banco de dados. Por exemplo, supondo que descobrimos que a propriedade 171 não aceita animais de estimação, podemos modificar a coluna pet_friendly usando WHERE em uma instrução UPDATE da seguinte forma:

UPDATE rentals
SET pet_friendly = false
WHERE property_id = 171;

Como usar a cláusula HAVING no SQL

Agora, é hora de você consultar a cláusula HAVING com o mesmo nível de detalhe. 

Sintaxe e declarações HAVING

Em primeiro lugar, você deve saber que a cláusula HAVING só pode ser usada em declarações SELECT. Portanto, a única sintaxe que ele pode ter é a seguinte:

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

Observe que você pode adicionar mais de uma coluna agrupada e mais de uma coluna agregada. Veremos exemplos a seguir.

Como escrever condições HAVING

Assim como WHERE, as condições de HAVING são escritas como expressões lógicas, mas com um componente adicional, a função de agregação. Portanto, uma condição HAVING consiste em 1) função agregada, 2) variável/operando, 3) operador de comparação e 4) valor/resultado.

Funções agregadas com HAVING

O SQL tem principalmente cinco funções de agregação, além de uma sexta que é um caso especial. Essas funções são:

Função agregada Tipo de dados adequado
SUM() Numérico
AVG() Numérico
MIN() Numérico, texto, data/carimbo de data/hora
MAX() Numérico, texto, data/carimbo de data/hora
COUNT() Numérico, texto, data/carimbo de data/hora, booleano

Vamos tentar um exemplo. Aqui, usamos a função COUNT() com GROUP BY para criar uma tabela de frequência e usar a condição HAVING como um filtro. Especificamente, precisamos conhecer as cidades que são mencionadas 150 vezes ou menos, o que, nesse contexto, tem a ver com o número de registros. Podemos usar essa consulta:

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

Usando MAX() com HAVING

Usando COUNT() com HAVING. Imagem do autor.

Operadores lógicos e de comparação

HAVING aceita todos os operadores lógicos e de comparação que o site WHERE aceita. A única diferença é que o tipo de dados adequado com HAVING depende principalmente da função de agregação, como podemos ver na tabela acima.

Casos de uso do HAVING

Ao contrário de WHERE, HAVING não pode ser usado nas declarações UPDATE e DELETE; HAVING é usado somente para recuperação de dados. Em termos gerais, isso se traduz em dois cenários:

Filtragem em nível de grupo

Esse é o uso comum e normal do site HAVING. Um exemplo é retornar apenas as cidades que têm preços médios de aluguel abaixo de US$ 2.700.

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

Filtragem de uma linha

Esse é um caso incomum, mas o site HAVING pode ser usado para retornar uma agregação de uma única linha, como uma métrica ou um KPI, somente se ela atender a uma determinada condição. Isso pode ser obtido por meio do uso do site HAVING sem GROUP BY. No exemplo a seguir, retornamos o preço médio do aluguel somente se ele estiver abaixo de US$ 2.800. Se a medida atender à condição, teremos um resultado de uma única linha. Caso contrário, teríamos uma mesa vazia.

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

Combinação de WHERE e HAVING

WHERE e HAVING podem ser combinados para filtrar tabelas antes e depois da agregação. No exemplo a seguir, retornamos a contagem de propriedades em cada cidade, contando apenas as propriedades que aceitam animais de estimação e filtrando apenas as cidades que têm mais de 80 propriedades.

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

Combinação de WHERE com HAVING

Combinação básica de WHERE e HAVING. Imagem do autor.

A diferença entre WHERE e HAVING no desempenho

Sabemos que a cláusula WHERE é aplicada antes do agrupamento ou da agregação. Mas também devemos saber que, por esse motivo, por reduzir o número de linhas processadas no início da consulta, o site WHERE é mais eficiente para filtrar linhas individuais. 

Sabemos, por outro lado, que a cláusula HAVING é aplicada após a agregação e filtra o conjunto de resultados com base nos dados agrupados. Por esse motivo, como ele processa os dados depois que todas as linhas foram agrupadas, geralmente é menos eficiente que o WHERE, embora ainda seja necessário para as condições que envolvem funções agregadas.

Vamos dar uma olhada nessa consulta:

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

Essa consulta é ineficiente porque a condição rental_price não depende de nenhuma agregação - ela filtra linhas individuais. Essa consulta primeiro agrupa todos os aluguéis por cidade, conta-os e depois filtra o resultado, o que é ineficiente porque processa linhas desnecessárias. Por esse motivo, essa teria sido uma consulta mais rápida:

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

Dicas de otimização de WHERE e HAVING

Com base no exposto, podemos ver algumas das boas práticas que podem otimizar nosso uso das cláusulas WHERE e HAVING. Isso é importante se você tiver grandes conjuntos de dados.

  1. Seja altamente seletivo: Filtre de acordo com os valores que você precisa filtrar e nada mais. Isso ajudará a reduzir o número de linhas na exibição e, portanto, aumentará a eficiência da consulta.

  2. Seja simples: Retire todas as condições, agregações e moldes de tipos desnecessários. Todos esses extras definitivamente vêm com um preço computacional.

  3. Filtro antecipado: Se você estiver fazendo uma agregação em nível de grupo, pré-filtre as linhas com WHERE para tornar o processo de agrupamento mais rápido. Ao fazer isso, você reduziria o número de linhas que precisam ser processadas no agrupamento.

Tabela de comparação

Vamos resumir nossos pensamentos em uma tabela conveniente:

Comparação ONDE TENDO
Objetivo principal Filtragem em nível de linha Filtragem em nível de grupo
Sintaxe básica SELECT coluna1, coluna2... FROM nome_da_tabela WHERE condição; SELECT grouped_column, aggregate_function(aggregated_column)... FROM table_name GROUP BY grouped_column HAVING condition;
Ordem de avaliação Antes de GROUP BY Depois de GROUP BY
Declarações compatíveis SELECIONAR, ATUALIZAR, EXCLUIR  SELECIONAR
Condições Não é possível incluir funções agregadas Deve incluir funções agregadas
Casos de uso Filtragem em nível de linha Recuperação de dados Manipulação de dados Filtragem em nível de grupo Filtragem de linha única
Subconsultas Pode trabalhar com subconsultas Deve ser escrito como CTEs

Conclusão

Ao longo do artigo, exploramos a principal diferença entre WHERE e HAVING no SQL, que é o fato de a cláusula WHERE filtrar as linhas antes da agregação, enquanto a cláusula HAVING filtra os dados agrupados após a agregação. Também exploramos algumas das diferenças menos conhecidas, como o fato de que WHERE pode funcionar com os comandos SELECT, UPDATE e DELETE, mas HAVING funciona somente com SELECT. Também conversamos um pouco sobre desempenho.

O SQL Basics Cheat Sheet da DataCamp oferece um bom resumo das cláusulas WHERE e HAVING, além de algumas orientações sobre como fazer filtragem no SQL. Além disso, se você estiver começando a trabalhar com SQL, poderá dar uma olhada na trilha de habilidades SQL Fundamentals e na trilha de carreira Associate Data Analyst in SQL


Islam Salahuddin's photo
Author
Islam Salahuddin

Islam é analista de dados, facilitador do The KPI Institute e professor da Universidade do Cairo. Com formação em jornalismo, Islam tem interesses diversos, incluindo redação, filosofia, mídia, tecnologia e cultura.

Perguntas frequentes

Qual é a diferença entre WHERE e HAVING?

WHERE faz a filtragem em nível de linha, enquanto HAVING faz a filtragem em nível de grupo.

Posso combinar WHERE e HAVING em uma única consulta?

Sim, e é altamente recomendável usar WHERE se você for usar HAVING.

O WHERE pode trabalhar com funções agregadas como HAVING?

Não, somente o site HAVING pode trabalhar com funções agregadas.

O WHERE e o HAVING funcionam com os mesmos operadores lógicos e de comparação?

Sim, ambos funcionam com os mesmos operadores, pois as condições WHERE e HAVING são escritas como expressões lógicas.

Posso usar HAVING sem GROUP BY?

HAVING geralmente é usado após o agrupamento com GROUP BY. A única exceção a isso é a filtragem de exibição de um valor (como o cálculo de uma métrica).

Temas

Aprenda SQL com a DataCamp

curso

Introduction to SQL

2 hr
1M
Learn how to create and query relational databases using SQL in just two hours.
Ver DetalhesRight Arrow
Iniciar curso
Ver maisRight Arrow
Relacionado

blog

SQL Server, PostgreSQL, MySQL... qual é a diferença? Por onde devo começar?

Neste tutorial, você aprenderá algumas das diferenças básicas entre os dialetos SQL e por onde deve começar.
Mona Khalil's photo

Mona Khalil

5 min

tutorial

Como usar GROUP BY e HAVING no SQL

Um guia intuitivo para você descobrir os dois comandos SQL mais populares para agregar linhas do seu conjunto de dados
Eugenia Anello's photo

Eugenia Anello

6 min

tutorial

QUALIFICAR: A instrução de filtragem SQL que você nunca soube que precisava

Saiba mais sobre a cláusula SQL QUALIFY, um método de filtragem essencial, porém menos conhecido, no SQL. Entenda sua sintaxe, usos e como ela difere de outros métodos de filtragem SQL.
Kurtis Pykes 's photo

Kurtis Pykes

8 min

tutorial

Como usar um alias SQL para simplificar suas consultas

Explore como o uso de um alias SQL simplifica os nomes de colunas e tabelas. Saiba por que usar um alias SQL é fundamental para melhorar a legibilidade e gerenciar uniões complexas.
Allan Ouko's photo

Allan Ouko

9 min

tutorial

FUNÇÃO SQL COUNT()

COUNT() permite que você conte o número de linhas que correspondem a determinadas condições. Saiba como usá-lo neste tutorial.
Travis Tang 's photo

Travis Tang

3 min

tutorial

Exemplos e tutoriais de consultas SQL

Se você deseja começar a usar o SQL, nós o ajudamos. Neste tutorial de SQL, apresentaremos as consultas SQL, uma ferramenta poderosa que nos permite trabalhar com os dados armazenados em um banco de dados. Você verá como escrever consultas SQL, aprenderá sobre
Sejal Jaiswal's photo

Sejal Jaiswal

21 min

Ver maisVer mais