curso
A diferença entre WHERE e HAVING no SQL
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 comGROUP 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 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 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é.
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’;
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';
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 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 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.
-
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.
-
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.
-
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 é 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).
Aprenda SQL com a DataCamp
curso
Intermediate SQL
curso
Data Manipulation in SQL
blog
SQL Server, PostgreSQL, MySQL... qual é a diferença? Por onde devo começar?
tutorial
Como usar GROUP BY e HAVING no SQL

Eugenia Anello
6 min
tutorial
QUALIFICAR: A instrução de filtragem SQL que você nunca soube que precisava
tutorial
Como usar um alias SQL para simplificar suas consultas

Allan Ouko
9 min
tutorial
FUNÇÃO SQL COUNT()
tutorial